API डॉक्यूमेंटेशन
पब्लिक API /v1: API key से ऑथेंटिकेट करें और अपने सॉफ़्टवेयर से इनबॉक्स का किराया ऑटोमेट करें
आपकी API key
आप लॉगिन नहीं हैं; अपनी API key पाने के लिए लॉगिन करें।
यह key Authorization: Bearer <key> हेडर में या ?api_key=<key> क्वेरी पैरामीटर में भेजें। पूरी key देखने के लिए आँख वाले आइकन पर क्लिक करें; बदलने की ज़रूरत हो तो नई key बनाएं पर क्लिक करें (पुरानी key तुरंत काम करना बंद कर देती है)।ओवरव्यू
Base URL
https://otpgmail.netऑथेंटिकेशन
हर रिक्वेस्ट में अपनी API key जोड़ें, या तो
Authorization: Bearer og_xxx... हेडर में (सुझाया गया) या ?api_key=og_xxx... क्वेरी स्ट्रिंग में।Idempotency-Key (डुप्लीकेट ऑर्डर से बचाव)
हर
POST /v1/orders रिक्वेस्ट में Idempotency-Key: <हर ऑर्डर के लिए नया UUID> हेडर जोड़ना चाहिए। अगर रिक्वेस्ट टाइमआउट हो जाए या कनेक्शन टूट जाए, तो उसे वही key लगाकर दोबारा भेजें: सर्वर नया ऑर्डर बनाने की जगह पहला जवाब ही लौटा देता है। हर नए ऑर्डर के लिए नया UUID बनाएं और UUID तभी दोहराएं जब रिट्राई कर रहे हों।एक साथ कई ऑर्डर: एक कॉल में स्टेटस
दर्जनों या सैकड़ों इनबॉक्स किराये पर ले रहे हैं? उनका स्टेटस एक साथ पढ़ें:
POST /v1/orders/status एक कॉल में 100 तक ऑर्डर लौटाता है (आपकी रेट लिमिट में एक ही अनुरोध गिना जाता है), और GET /v1/orders आपके ऑर्डर की सूची देता है — रीस्टार्ट के बाद ?status=waiting_code वे सभी ऑर्डर लौटा देता है जो अभी कोड का इंतज़ार कर रहे हैं। हर एरर यह भी बताता है कि दोबारा कोशिश करनी है या नहीं (error.retryable, error.retryAfterSec)। विवरण: कई ऑर्डर का स्टेटस सेक्शन।इनबॉक्स टाइप: Gmail या iCloud
डिफ़ॉल्ट रूप से आपको
@gmail.com इनबॉक्स मिलता है। @icloud.com इनबॉक्स किराए पर लेने के लिए POST /v1/orders की body में "domain": "icloud.com" जोड़ें। domain न भेजने का मतलब gmail.com है — मौजूदा इंटीग्रेशन बिना किसी बदलाव के चलते रहेंगे। iCloud सिर्फ़ उन सर्विस के लिए उपलब्ध है जिनका icloud फ़ील्ड GET /v1/services में null नहीं है; iCloud की कीमत Gmail से अलग हो सकती है (icloud.price देखें)। हर ऑर्डर के रिस्पॉन्स में domain फ़ील्ड होता है जो बताता है कि ऑर्डर किस इनबॉक्स टाइप का है। कुछ सर्विस @gmx.com इनबॉक्स भी देती हैं (अभी सिर्फ़ Pokemon, कोड pkm, warehouse 2): "domain": "gmx.com" भेजें; सर्विस यह तब देती है जब GET /v1/services में उसके offers[] में domain = "gmx.com" वाली एंट्री हो; किसी और सर्विस पर ⇒ DOMAIN_UNAVAILABLE। gmx.com लॉट के लिए उपलब्ध नहीं है।Warehouse: एक सर्विस, कई इनबॉक्स सोर्स
एक सर्विस कई Warehouse से बिक सकती है, हर एक की अपनी कीमत, स्टॉक और कोड के नियम होते हैं (
GET /v1/services में offers[] ऐरे)। ऑर्डर बनाते समय "warehouse": 2 भेजकर एक चुनें; "warehouse": 99 ⇒ सिस्टम स्टॉक में उपलब्ध सबसे कम कीमत वाला Warehouse चुनता है और वह खत्म हो जाए तो अगले पर चला जाता है (उन सर्विस के लिए सबसे अच्छा जिनका स्टॉक अक्सर खत्म होता है, जैसे Facebook और Instagram); 0 ⇒ स्टॉक में उपलब्ध सबसे कम कीमत वाला Warehouse। मौजूदा क्लाइंट को कोई बदलाव नहीं करना है: warehouse न भेजने पर ⇒ पहले की तरह warehouse 1, और price, stock व icloud warehouse 1 का ब्योरा देते हैं (जिन सर्विस में warehouse 1 नहीं है ⇒ स्टॉक में उपलब्ध सबसे कम कीमत वाला Warehouse)। विवरण: Warehouse देखें।लॉट में किराया (batches)
लॉट वेब पर खरीदे जाते हैं (लॉट में किराया पेज); API से आप लॉट की लिस्ट और कोड पढ़ सकते हैं। Gmail (Warehouse 1): हर इनबॉक्स का एक
proxyUrl होता है, यानी बिना API key वाला कोड लिंक। iCloud (Warehouse 3): प्राइवेट इनबॉक्स; कोड GET /v1/batches/{id}/mails/{mailId}/codes से पढ़ें या वेब पर readUrl खोलें। विवरण: लॉट में किराया सेक्शन देखें।कम समय चलने वाले Gmail अकाउंट खरीदें (mail shop)
इनबॉक्स किराए पर लेने के अलावा, आप 2 Warehouse से पूरे Gmail अकाउंट खरीद सकते हैं — Warehouse 1: ईमेल, पासवर्ड, कुकीज़ + इनबॉक्स लिंक (JSON में भी); Warehouse 2: ईमेल, पासवर्ड + क्विक लॉगिन लिंक; Warehouse 99 सबसे सस्ता पहले चुनता है (वेब पर कम समय चलने वाला Gmail खरीदें पेज)। जो कुछ वह पेज करता है, वह सब API से भी होता है: Warehouse, कीमतें और स्टॉक देखना, खरीदना (
Idempotency-Key ज़रूरी), डिलीवरी पर नज़र रखना, अकाउंट डाउनलोड करना और उनके ईमेल पढ़ना। विवरण: कम समय चलने वाला Gmail खरीदें सेक्शन देखें।आपके ग्राहक खुद कोड देखें (/otp पेज)
किराए पर लिए इनबॉक्स (वेब या API से) आगे बेचते हैं? अकाउंट पेज पर शेयर कोड चालू करें, फिर ग्राहक को लिंक
https://otpgmail.net/hi/otp#k7m2q9:[email protected] भेजें (k7m2q9 = आपका शेयर कोड) — वे लॉग-इन किए बिना उस ईमेल के ताज़ा कोड देखते हैं, कीमत या आपका बैलेंस कभी नहीं देखते; पेज सिर्फ़ बिना शुल्क वाले काम करता है (आपसे कभी पैसे नहीं काटता)।टूल / बॉट के लिए JSON लिंक (आपके या आपके ग्राहक के): पाथ वाला लिंक
https://otpgmail.net/hi/otp/k7m2q9:[email protected] लें (यह # वाले लिंक की तरह /otp पेज खोलता है) और उसके अंत में ?json जोड़ें ⇒ सर्वर ठीक वही डेटा JSON में लौटाता है जो पेज दिखाता है: cards[] — उस ईमेल पर किराए पर ली गई हर सेवा का एक कार्ड (email, serviceName, state, items[] = नए से पुराने क्रम में अधिकतम 5 ताज़ा कोड / लिंक) — और serverTime। state: waiting पहले कोड का इंतज़ार · listening नए कोड का इंतज़ार · received कोड आ गया · needs_owner विक्रेता को समय बढ़ाना होगा · expired समय खत्म · banned इनबॉक्स लॉक। कई ईमेल: कॉमा से अलग करें (अधिकतम 50)। API की और कुकी की ज़रूरत नहीं, CORS खुला है; सिर्फ़ पढ़ने के लिए (“नया OTP लोड करें” / “यह ईमेल फिर से किराए पर लें” /otp पेज पर ही रहते हैं)। अनुमान से बचाव की वही सीमाएँ जो पेज पर हैं: गलत कोड / ईमेल पर दिखाने लायक कोई ऑर्डर नहीं ⇒ 404 NOT_FOUND; बार-बार गलती या एक ईमेल के लिए प्रति मिनट 30 से ज़्यादा बार पढ़ना ⇒ 429 RATE_LIMITED साथ में retryAfter (सेकंड)। /otp#… लिंक में ?json जोड़ने से JSON नहीं मिलता: ब्राउज़र # के बाद वाला हिस्सा सर्वर को कभी नहीं भेजता।curl "https://otpgmail.net/hi/otp/k7m2q9:[email protected]?json"{
"success": true,
"data": {
"cards": [
{
"ref": "Q3vX9kL2mP0aB7cD",
"serviceCode": "fb",
"serviceName": "Facebook",
"logo": "/logos/fb.png?v=20261007",
"domain": "gmail.com",
"email": "[email protected]",
"state": "received",
"until": null,
"items": [
{
"kind": "code",
"value": "529170",
"label": null,
"at": 1760000405
},
{
"kind": "code",
"value": "381904",
"label": null,
"at": 1759999030
}
],
"total": 2,
"canLoad": true
}
],
"serverTime": 1760000530
}
}GitHub पर पूरा सैंपल कोड
Python, Node.js, PHP, C# (.NET) और curl के तैयार क्लाइंट, जो सीधे चलाए जा सकते हैं: इनबॉक्स किराए पर लें, कोड का इंतज़ार करें, रिफंड के लिए अपने-आप कैंसल करें, और स्टॉक खत्म होने पर iCloud और Gmail के बीच बदलें: github.com/letoan0902/otpgmail-email-otp-api (अंग्रेज़ी) · thue-otp-gmail (वियतनामी)। Python के लिए ध्यान दें: सीधे
urllib की जगह requests इस्तेमाल करें (उसका डिफ़ॉल्ट User-Agent CDN से 403 पाता है)।वेबहुक
हर ऑर्डर को बार-बार पूछने के बजाय एक URL रजिस्टर करें और जैसे ही किसी ऑर्डर को नया कोड मिले या वह रद्द / रिफ़ंड हो, हस्ताक्षरित POST पाएँ — देखें वेबहुक।
Endpoints
GET/v1/balance
रिक्वेस्ट में इस्तेमाल हुई API key के अकाउंट का बैलेंस (VND में) लौटाता है।
उदाहरणcurl
Python
Node.js
curl "https://otpgmail.net/v1/balance" \
-H "Authorization: Bearer og_xxx..."{
"success": true,
"data": {
"balance": 25000
}
}संभावित एरर: UNAUTHORIZEDGET/v1/services
चालू सर्विस की लिस्ट लौटाता है: कोड, नाम, Gmail की कीमत (VND में) और मौजूदा Gmail स्टॉक, @icloud.com इनबॉक्स की कीमत और स्टॉक वाला icloud ब्लॉक, और offers[] ऐरे: उस सर्विस को बेचने वाले हर warehouse की एंट्री, यानी हर warehouse × इनबॉक्स टाइप पर एक (कीमत, स्टॉक, कोड की संख्या, नियम)। डेटा कैश होता है: स्टॉक लगभग हर 30–60 सेकंड में रिफ्रेश होता है, कीमतें इससे कम बार।
icloud = null का मतलब है कि सर्विस अभी iCloud सपोर्ट नहीं करती (प्रोवाइडर उसे नहीं देता, या वह कुछ देर के लिए बंद है) — सिर्फ़ Gmail किराए पर लिया जा सकता है। icloud ब्लॉक वाली सर्विस के लिए, ऑर्डर बनाते समय "domain": "icloud.com" भेजें ताकि icloud.price पर @icloud.com इनबॉक्स मिले। price / stock / icloud.price warehouse 1 का ब्योरा देते हैं — जहाँ बिना warehouse वाले ऑर्डर जाते हैं (जिन सर्विस में warehouse 1 नहीं है ⇒ स्टॉक में उपलब्ध सबसे कम कीमत वाला warehouse); हर warehouse की कीमत और स्टॉक offers[] में हैं (Warehouse सेक्शन देखें)। stock वह संख्या है जो स्रोत बताता है (Warehouse 1: लगभग हर 30 सेकंड में अपडेट), यह वादा नहीं कि एक कॉल में उतने किराए पर मिल जाएंगे: इनबॉक्स एक-एक करके दिए जाते हैं और स्रोत बीच में खत्म हो सकता है — तब POST /v1/orders कम ऑर्डर और एक partial फ़ील्ड लौटाता है। Warehouse 2 और 4 भी अपने-अपने स्रोत की संख्या दिखाते हैं।
उदाहरणcurl
Python
Node.js
curl "https://otpgmail.net/v1/services" \
-H "Authorization: Bearer og_xxx..."{
"success": true,
"data": [
{
"code": "dr",
"name": "OpenAI (ChatGPT)",
"price": 350,
"stock": 616525,
"icloud": {
"price": 630,
"stock": 12464
},
"offers": [
{
"warehouse": 2,
"domain": "gmail.com",
"price": 350,
"stock": 616525,
"maxCodes": null,
"rules": null,
"fee": {
"freeHours": 6,
"paidPct": 50,
"maxHours": 24
},
"isDefault": true
},
{
"warehouse": 1,
"domain": "gmail.com",
"price": 630,
"stock": 12464,
"maxCodes": 3,
"rules": null,
"fee": null,
"isDefault": false
},
{
"warehouse": 1,
"domain": "icloud.com",
"price": 630,
"stock": 12464,
"maxCodes": 5,
"rules": null,
"fee": null,
"isDefault": true
}
],
"note": null
},
{
"code": "fb",
"name": "Facebook",
"price": 1590,
"stock": 88,
"icloud": null,
"offers": [
{
"warehouse": 1,
"domain": "gmail.com",
"price": 1590,
"stock": 88,
"maxCodes": 10,
"rules": null,
"fee": null,
"isDefault": false
},
{
"warehouse": 4,
"domain": "gmail.com",
"price": 1580,
"stock": 2310,
"maxCodes": null,
"rules": null,
"fee": null,
"isDefault": true
}
],
"note": null
}
]
}संभावित एरर: UNAUTHORIZEDPOST/v1/orders
वेरिफिकेशन कोड पाने वाले इनबॉक्स का ऑर्डर बनाता है — डिफ़ॉल्ट रूप से Gmail, या domain: "icloud.com" भेजने पर iCloud। प्रोवाइडर के इनबॉक्स देते ही आपका बैलेंस कट जाता है। ऑर्डर की लिस्ट लौटाता है (एक, या quantity > 1 होने पर कई)।
आंशिक डिलीवरी: quantity एक अधिकतम सीमा है
- इनबॉक्स एक-एक करके दिए जाते हैं। अगर प्रोवाइडर के इनबॉक्स बीच में खत्म हो जाएं (जैसे उस समय Warehouse 1 में उस सर्विस के लिए और इनबॉक्स न हों), तो कॉल रुक जाता है और अब तक बने ऑर्डर के साथ HTTP 200 लौटाता है —
dataquantity से छोटा हो सकता है, और पैसे सिर्फ़dataवाले ऑर्डर के कटते हैं।GET /v1/servicesकाstockइसकी गारंटी नहीं है कि एक कॉल में कितने मिलेंगे। - ऐसे में जवाब में
dataके साथ ऊपरी स्तर का एकpartialफ़ील्ड भी होता है (सब मिल जाने पर यह नहीं होता — जो बॉट सिर्फ़dataपढ़ते हैं, वे बिना बदलाव चलते रहते हैं):requested,delivered,missingऔरreason={code, message, retryable, retryAfterSec}, जहाँcodeवह एरर है जिसने कॉल रोका (NO_MAILS_AVAILABLE,OUT_OF_STOCK,ALL_WAREHOUSES_EXHAUSTED,INSUFFICIENT_BALANCE,WAITING_LIMIT_REACHED…)। - इनबॉक्स खत्म होना आम तौर पर अस्थायी होता है — Warehouse 1 में कुछ सेकंड बाद प्रोवाइडर के पास अक्सर फिर इनबॉक्स आ जाते हैं। जब
reason.retryable= true हो:reason.retryAfterSecसेकंड (3–5 सेकंड) रुकें, फिर बचे हुए इनबॉक्स (missing) नईIdempotency-Keyके साथ दोबारा मांगें (पुरानी key सिर्फ़ यही जवाब दोबारा लौटाती है); सब मिलने तक दोहराएं। - आंशिक डिलीवरी के ठीक बाद अगला कॉल 409
WAREHOUSE_UNAVAILABLE/OUT_OF_STOCKया 503NO_MAILS_AVAILABLEलौटा सकता है — यह सामान्य है: कॉल के बीच 3–5 सेकंड का अंतर रखते रहें और तभी रुकें जब लगातार कई कॉल फ़ेल हों (जैसे 10 कोशिशें, लगभग एक मिनट); फिर बाद में कोशिश करें, या"warehouse": 99भेजें ताकि सिस्टम दूसरे Warehouse पर चला जाए।retryable= false (INSUFFICIENT_BALANCE,WAITING_LIMIT_REACHED…) ⇒ पहले वजह ठीक करें (बैलेंस भरें, या खुले ऑर्डर पूरे होने दें)। - एरर वाले जवाबों में भी यही दो फ़ील्ड
errorके अंदर होते हैं:error.retryableऔरerror.retryAfterSec(जैसे 409OUT_OF_STOCK⇒true, 5; 402INSUFFICIENT_BALANCE⇒false,null) — एरर कोड देखें।
Idempotency-Key हेडर (एक UUID) ज़रूरी है। हर नए किराए के लिए नया UUID बनाएं; टाइमआउट के बाद रिट्राई करते समय डुप्लीकेट ऑर्डर से बचने के लिए वही key दोबारा इस्तेमाल करें। यह कॉल प्रोवाइडर के इनबॉक्स देने का इंतज़ार करता है, इसलिए आम तौर पर लगभग 0.3 सेकंड लेता है पर भीड़ के समय (कभी-कभार) 10 सेकंड तक लग सकता है — अपने क्लाइंट का टाइमआउट लगभग 15 सेकंड रखें, 5 सेकंड बाद हार मानकर जल्दी रिट्राई न करें।
पैरामीटर| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
service | string | हाँ | सर्विस कोड (GET /v1/services से, जैसे "ig", "tg", "fb") |
quantity | number | नहीं | ज़्यादा से ज़्यादा कितने इनबॉक्स किराए पर लेने हैं (डिफ़ॉल्ट 1; प्रति रिक्वेस्ट अधिकतम 200) — Warehouse बीच में खत्म हो जाए तो कम मिलते हैं: data[] गिनें और partial पढ़ें |
domain | string | नहीं | इनबॉक्स टाइप: "gmail.com" (डिफ़ॉल्ट), "icloud.com" या "gmx.com"। न भेजने पर = gmail.com — मौजूदा इंटीग्रेशन को बदलाव की ज़रूरत नहीं। iCloud सिर्फ़ उन सर्विस के लिए लिया जा सकता है जिनका icloud फ़ील्ड GET /v1/services में null नहीं है; "gmx.com" सिर्फ़ उन सर्विस के लिए जिनमें offers[].domain = "gmx.com" है (अभी सिर्फ़ Pokemon, कोड pkm) — नहीं तो कॉल DOMAIN_UNAVAILABLE से फेल होती है। कोई और वैल्यू ⇒ VALIDATION_ERROR। |
warehouse | number | नहीं | किस Warehouse से किराए पर लेना है। न भेजने पर = WAREHOUSE 1, ठीक वैसे ही जैसे multi-warehouse से पहले था (जिन सर्विस में warehouse 1 नहीं है वे सबसे कम कीमत वाले पर जाती हैं) — मौजूदा क्लाइंट को बदलाव की ज़रूरत नहीं। 0 = स्टॉक में उपलब्ध सबसे कम कीमत वाला warehouse (सिर्फ़ एक warehouse आज़माया जाता है)। 1–4 = ठीक वही warehouse (GET /v1/services के offers[].warehouse से); अगर वह यह सर्विस/इनबॉक्स टाइप नहीं बेचता, रुका हुआ है या उसका स्टॉक खत्म है ⇒ WAREHOUSE_UNAVAILABLE। 99 = ऑटोमैटिक: स्टॉक वाले warehouse सबसे कम कीमत से सबसे ज़्यादा कीमत के क्रम में आज़माए जाते हैं, और स्टॉक खत्म या फेल होने पर अगले पर जाते हैं; कोई न बचे ⇒ ALL_WAREHOUSES_EXHAUSTED — उन सर्विस के लिए सुझाया गया जिनका स्टॉक अक्सर खत्म होता है (Facebook, Instagram…)। Warehouse सेक्शन देखें। |
curl
Python
Node.js
# हर नए ऑर्डर के लिए नई रैंडम Idempotency-Key बनाएं
# टाइमआउट के बाद रिट्राई करते समय वही key दोबारा इस्तेमाल करें (डुप्लीकेट ऑर्डर से बचाव)
# domain: "gmail.com" (डिफ़ॉल्ट, वैकल्पिक) | "icloud.com" (@icloud.com इनबॉक्स किराए पर लें) | "gmx.com" (सिर्फ़ वे सर्विस जो इसे देती हैं, जैसे Pokemon)
# warehouse: 0 | 1–4 | 99 (वैकल्पिक — पहले की तरह warehouse 1 के लिए इसे न भेजें; 0 = स्टॉक में उपलब्ध सबसे कम कीमत वाला warehouse; 99 = ऑटोमैटिक, एक खत्म होने पर अगले पर जाता है; GET /v1/services में offers[] देखें)
curl -X POST "https://otpgmail.net/v1/orders" \
-H "Authorization: Bearer og_xxx..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"service":"ig","quantity":1,"domain":"gmail.com"}'{
"success": true,
"data": [
{
"orderId": "abc123xyz",
"service": "ig",
"domain": "gmail.com",
"email": "[email protected]",
"status": "waiting_code",
"price": 1060,
"otp": [],
"codeDeadlineAt": 1753270000,
"rentExpiresAt": 1753356400,
"createdAt": 1753268200,
"warehouse": 1,
"nextCodeFee": null,
"listening": false,
"listenUntil": null,
"nextCodeBlocked": false,
"nextCodeBlockReason": null
}
]
}सैंपल जवाब — आंशिक डिलीवरी (quantity 5, 2 इनबॉक्स मिले)
संभावित एरर: {
"success": true,
"data": [
{
"orderId": "abc123xyz",
"service": "ig",
"domain": "gmail.com",
"email": "[email protected]",
"status": "waiting_code",
"price": 1060,
"otp": [],
"codeDeadlineAt": 1753270000,
"rentExpiresAt": 1753356400,
"createdAt": 1753268200,
"warehouse": 1,
"nextCodeFee": null,
"listening": false,
"listenUntil": null,
"nextCodeBlocked": false,
"nextCodeBlockReason": null
},
{
"orderId": "jkl012mno",
"service": "ig",
"domain": "gmail.com",
"email": "[email protected]",
"status": "waiting_code",
"price": 1060,
"otp": [],
"codeDeadlineAt": 1753270001,
"rentExpiresAt": 1753356401,
"createdAt": 1753268201,
"warehouse": 1,
"nextCodeFee": null,
"listening": false,
"listenUntil": null,
"nextCodeBlocked": false,
"nextCodeBlockReason": null
}
],
"partial": {
"requested": 5,
"delivered": 2,
"missing": 3,
"reason": {
"code": "NO_MAILS_AVAILABLE",
"message": "No inboxes available for this service right now, please try again later",
"retryable": true,
"retryAfterSec": 5
}
}
}UNAUTHORIZED, VALIDATION_ERROR, SERVICE_DISABLED, INSUFFICIENT_BALANCE, OUT_OF_STOCK, DOMAIN_UNAVAILABLE, WAREHOUSE_UNAVAILABLE, ALL_WAREHOUSES_EXHAUSTED, NO_MAILS_AVAILABLE, QUANTITY_EXCEEDED, WAITING_LIMIT_REACHED, RATE_LIMITED, DUPLICATE_REQUEST, PROVIDER_ERROR, MAINTENANCEGET/v1/orders/{id}
ID से ऑर्डर लौटाता है, अब तक मिले कोड (otp[]) समेत। ऑर्डर जब तक waiting_code स्टेटस में है, कोड पाने के लिए इस endpoint को हर 3–5 सेकंड में poll करें।
otp[] ऐरे आने के क्रम में होता है: सबसे पुराना पहले, सबसे नया आखिर में — ताज़ा कोड otp[otp.length - 1] से पढ़ें। हर कॉल पर सिस्टम अभी खुले ऑर्डर के लिए हर warehouse की अपनी रफ़्तार से (हर कुछ सेकंड में) प्रोवाइडर से जाँच करता है — इससे ज़्यादा बार कॉल करने पर बस सेव किया हुआ डेटा मिलता है। पहले कोड के बाद poll करते रहें: अगले कोड (अगर सर्विस एक से ज़्यादा भेजे) ऑर्डर की अवधि में बिना अतिरिक्त शुल्क otp[] के अंत में जुड़ते हैं — सीमा और समय-विंडो किराए पर लेने से पहले दिखती है (offers[] में maxCodes और fee); सिस्टम नए कोड का इंतज़ार कर रहा है यह पक्का करने के लिए POST /v1/orders/{id}/next-code कॉल करें (हर warehouse में; शुल्क सिर्फ़ warehouse 2 अपनी बिना शुल्क वाली विंडो के बाहर लेता है)। अगर सर्विस हर इनबॉक्स पर सिर्फ़ एक कोड की इजाज़त देती है, तो otp[] उसी कोड पर रुक जाता है — रिस्पॉन्स सामान्य रहते हैं, कोई एरर नहीं। warehouse फ़ील्ड बताता है कि इनबॉक्स किस warehouse ने दिया (1–4); nextCodeFee और कोड का शुल्क है (warehouse 2 और 3 के ऑर्डर; warehouse 1 और 4 के लिए null) — Warehouse सेक्शन देखें। 2026-10-02 से ऑर्डर में nextCodeBlocked (true = इनबॉक्स अब और कोड नहीं पा सकता) और nextCodeBlockReason भी आते हैं — वजह: "email_banned" (ईमेल को सर्विस ने लॉक कर दिया — नया किराए पर लें), "activation_gone" (प्रोवाइडर ने इनबॉक्स बंद कर दिया), "hard_expired" (कोड की विंडो खत्म हो गई), "max_codes" (कोड की अधिकतम संख्या मिल चुकी), null (ब्लॉक नहीं / पुराना ऑर्डर जिसमें वजह दर्ज नहीं)। ये जोड़े गए फ़ील्ड हैं — मौजूदा क्लाइंट को बदलाव की ज़रूरत नहीं। कई ऑर्डर poll कर रहे हैं? हर ऑर्डर के लिए अलग GET की जगह एक कॉल में 100 तक ID POST /v1/orders/status पर भेजें — वही ऑर्डर ऑब्जेक्ट, रेट लिमिट में एक ही अनुरोध।
पैरामीटर| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
id | string | हाँ | ऑर्डर ID (ऑर्डर बनने पर मिला orderId) |
curl
Python
Node.js
curl "https://otpgmail.net/v1/orders/ORDER_ID" \
-H "Authorization: Bearer og_xxx..."{
"success": true,
"data": {
"orderId": "abc123xyz",
"service": "ig",
"domain": "gmail.com",
"email": "[email protected]",
"status": "completed",
"price": 1060,
"otp": [
{
"code": "123456",
"receivedAt": 1753268500
},
{
"code": "789012",
"receivedAt": 1753269000
}
],
"codeDeadlineAt": 1753270000,
"rentExpiresAt": 1753356400,
"createdAt": 1753268200,
"warehouse": 1,
"nextCodeFee": null,
"listening": true,
"listenUntil": 1753270500,
"nextCodeBlocked": false,
"nextCodeBlockReason": null
}
}संभावित एरर: UNAUTHORIZED, NOT_FOUNDPOST/v1/orders/{id}/cancel
ऑर्डर कैंसल करता है और कीमत का 100% रिफंड करता है। सिर्फ़ तब मुमकिन है जब ऑर्डर waiting_code स्टेटस में हो और कोई कोड न मिला हो।
जिस ऑर्डर को कोड मिल चुका है (एक भी), उसे कैंसल या रिफंड नहीं किया जा सकता — यह वेबसाइट और API दोनों पर लागू है। rules.cancellable = false वाले ऑर्डर (अपने इन्वेंटरी की सर्विस, जैसे Cointiply) कैंसल नहीं हो सकते: इनबॉक्स असाइन होने के बाद कैंसल या रिफंड नहीं होता — cancel कॉल ORDER_NOT_CANCELLABLE लौटाती है। सामान्य सर्विस के Warehouse-3 ऑर्डर (rules.cancellable = true) कोड आने से पहले किसी भी दूसरे ऑर्डर की तरह कैंसल हो सकते हैं।
पैरामीटर| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
id | string | हाँ | कैंसल किए जाने वाले ऑर्डर की ID |
curl
Python
Node.js
curl -X POST "https://otpgmail.net/v1/orders/ORDER_ID/cancel" \
-H "Authorization: Bearer og_xxx..." \
-H "Content-Type: application/json"{
"success": true,
"data": {
"orderId": "abc123xyz",
"service": "ig",
"domain": "gmail.com",
"email": "[email protected]",
"status": "cancelled",
"price": 1060,
"otp": [],
"codeDeadlineAt": 1753270000,
"rentExpiresAt": 1753356400,
"createdAt": 1753268200,
"warehouse": 1,
"nextCodeFee": null,
"listening": false,
"listenUntil": null,
"nextCodeBlocked": false,
"nextCodeBlockReason": null
}
}संभावित एरर: UNAUTHORIZED, NOT_FOUND, ORDER_NOT_CANCELLABLE, PROVIDER_ERRORPOST/v1/orders/{id}/rerent
अपने इन्वेंटरी की सर्विस (provider = "inventory", जैसे Cointiply) के ऑर्डर के लिए उसी इनबॉक्स को फिर किराए पर लेता है: उसी इनबॉक्स पर नई रिसीविंग विंडो के साथ एक नया ऑर्डर बनाता है, कीमत पुराने ऑर्डर का rerentPriceVnd होती है।
तभी चलता है जब पुराने ऑर्डर में canRerent = true हो (उस इनबॉक्स का सबसे नया ऑर्डर, जिसकी पिछली विंडो खत्म हो चुकी हो या जिसे सारे ईमेल मिल चुके हों)। सफल होते ही पैसे कट जाते हैं — Idempotency-Key भेजें और रिट्राई में वही दोबारा इस्तेमाल करें ताकि दो बार पैसे न कटें। रिस्पॉन्स { order, message } है; order का आकार GET /v1/orders/{id} जैसा है। Warehouse 2 (2026-10-09 से): ऐसा ऑर्डर जो रद्द हुआ, समय खत्म होने से बंद हुआ या एक्सपायर हुआ (इनबॉक्स बंद) — तब कॉल करें जब
पैरामीटरcanRerent = true हो (उस ईमेल का सबसे नया ऑर्डर, और ईमेल पर कोई दूसरा चालू ऑर्डर नहीं)। सिस्टम उसी ईमेल को एक नए ऑर्डर के रूप में फिर खोलता है (status = waiting_code), कीमत rerentPriceVnd (अभी आपकी कीमत का 100%), और किसी भी Warehouse 2 ऑर्डर की तरह ईमेल के लिए 20 मिनट इंतज़ार करता है — ईमेल न आए तो ऑर्डर रद्द होकर 100% रिफ़ंड होता है। सर्विस ने ईमेल लॉक किया ⇒ RERENT_EMAIL_BANNED; प्रोवाइडर उसे फिर नहीं खोल सकता ⇒ RERENT_MAIL_GONE; Warehouse 2 कुछ देर के लिए बंद ⇒ PROVIDER_ERROR — तीनों में पैसे नहीं कटते।| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
id | string | हाँ | इनबॉक्स के पिछले ऑर्डर की ID (जिसमें canRerent = true है) |
curl
Python
Node.js
# टाइमआउट के बाद रिट्राई करते समय वही key दोबारा इस्तेमाल करें (डुप्लीकेट ऑर्डर से बचाव)
curl -X POST "https://otpgmail.net/v1/orders/ORDER_ID/rerent" \
-H "Authorization: Bearer og_xxx..." \
-H "Idempotency-Key: $(uuidgen)"{
"success": true,
"data": {
"order": {
"orderId": "def456uvw",
"service": "ctp",
"domain": "icloud.com",
"email": "[email protected]",
"status": "waiting_code",
"price": 3500,
"otp": [],
"codeDeadlineAt": 1753273500,
"rentExpiresAt": 1753273500,
"createdAt": 1753269000,
"provider": "inventory",
"rules": {
"windowMinutes": 75,
"maxCodes": 4,
"cancellable": false,
"refundOnTimeout": false,
"rerentRatio": 0.5
},
"windowEndsAt": 1753273500,
"canRerent": false,
"rerentPriceVnd": 3500,
"warehouse": 3,
"nextCodeFee": null,
"listening": false,
"listenUntil": null,
"nextCodeBlocked": false,
"nextCodeBlockReason": null
},
"message": "Inbox rented again — a new 75-minute message window has started"
}
}संभावित एरर: UNAUTHORIZED, NOT_FOUND, RERENT_NOT_AVAILABLE, RERENT_EMAIL_BANNED, RERENT_MAIL_GONE, INSUFFICIENT_BALANCE, WAITING_LIMIT_REACHED, RATE_LIMITED, DUPLICATE_REQUEST, PROVIDER_ERROR, MAINTENANCEPOST/v1/orders/{id}/next-code
उसी इनबॉक्स पर अगला कोड माँगता है — हर warehouse (warehouse 1–4) के उन ऑर्डर के लिए काम करता है जिनमें पहला कोड आ चुका है (status = completed)। बिना शुल्क, सिवाय Warehouse-2 के उन ऑर्डर के जिनकी बिना शुल्क वाली विंडो खत्म हो चुकी है (nextCodeFee.feePriceVnd > 0): तब शुल्क चुकाने और एक और कोड विंडो खोलने के लिए confirmFee: true भेजें (अंतिम सीमा nextCodeFee.hardUntil तक)। आपके बॉट को warehouse जानने की ज़रूरत नहीं: GET /v1/orders/{id} को poll करते रहें — नए कोड otp[] के अंत में जुड़ते हैं — और जब चाहें कि सिस्टम नए कोड का इंतज़ार करे तब यह कॉल करें।
हर warehouse में यह कॉल क्या करती है
- Warehouse 1: ऑर्डर की अवधि (
rentExpiresAt) में हर कोड के बाद सिस्टम अपने-आप अगले कोड का इंतज़ार करता है — कॉल 200 लौटाती है और कुछ नहीं बदलती; इनबॉक्स में और कोड नहीं आ सकते (कोड की सीमा पूरी, इनबॉक्स बंद, समय खत्म) ⇒nextCodeBlockReasonके साथ 409। - Warehouse 2: प्रोवाइडर के पास इनबॉक्स फिर खोलता है (
reordered= true) और ईमेल के लिए 20 मिनट इंतज़ार करता है; बिना शुल्क वाली विंडो में कोई शुल्क नहीं (nextCodeFee.feePriceVnd= 0), विंडो के बाहरconfirmFee= true भेजना ज़रूरी है (न भेजें ⇒ 409NEXT_CODE_FEE_CONFIRM, कुछ नहीं कटता)। शुल्क तभी रखा जाता है जब नया कोड आए — 20 मिनट में कोई कोड न आए ⇒ अपने-आप वापसी। हर कोड के बाद सिस्टम अगले कोड का 25 मिनट और इंतज़ार करता है (listening= true,listenUntil)। - Warehouse 3 (सामान्य सर्विस): थोड़ी देर का इंतज़ार फिर खोलता है, बिना शुल्क वाली विंडो के अंदर कोई शुल्क नहीं (
nextCodeFee.freeUntil); विंडो के बाद ⇒ 409 —POST /v1/orders/{id}/rerentइस्तेमाल करें। Cointiply जैसी अपनी-इन्वेंटरी सर्विस (rules.cancellable= false) में यह कॉल नहीं है (409): विंडो के दौरान हर ईमेल अपने-आप दिखता है। - Warehouse 4: प्रोवाइडर के पास ऑर्डर दोबारा पढ़ता है और नए कोड का इंतज़ार करता है,
rentExpiresAtतक बिना शुल्क।
200 = सिस्टम इस ऑर्डर के लिए नए कोड का इंतज़ार कर रहा है (listening = true, listenUntil = इंतज़ार कब रुकेगा; इनबॉक्स अभी फिर खुला हो तो reordered = true; शुल्क कटा हो तो chargedVnd), या कॉल करते ही नया कोड आ गया (वह order.otp में मौजूद है)। 409 = नया इंतज़ार नहीं खुल सका — error.code पढ़ें; इनबॉक्स में और कोड क्यों नहीं आ सकते, यह order.nextCodeBlockReason (GET /v1/orders/{id}) में है। जो ऑर्डर अभी पहले कोड का इंतज़ार कर रहा है (waiting_code) ⇒ 409, अभी कॉल करने की ज़रूरत नहीं। पेड कॉल में Idempotency-Key भेजें (रिट्राई में वही दोबारा इस्तेमाल करें ताकि दो बार पैसे न कटें)। प्रोवाइडर तक नहीं पहुँचे ⇒ 502 PROVIDER_ERROR, बाद में फिर कोशिश करें। इस कॉल के 409 एरर कोड: NEXT_CODE_FEE_CONFIRM (warehouse 2 में शुल्क चाहिए — confirmFee: true के साथ फिर कॉल करें), EMAIL_BANNED (सर्विस ने ईमेल लॉक कर दिया — नया किराए पर लें; error.details.blockReason = "email_banned"), ORDER_EXPIRED (समय खत्म, इनबॉक्स बंद, कोड की सीमा पूरी, या सर्विस में "अगला कोड" नहीं है — वजह order.nextCodeBlockReason में), ORDER_NOT_CANCELLABLE (ऑर्डर में अभी पहला कोड नहीं आया)। जो बॉट इस कॉल के किसी भी 409 को “और कोड नहीं” मानते हैं वे बिना बदलाव चलते रहेंगे। refresh: true (warehouse 2): पहले नया ईमेल जाँचा जाता है (अभी आया ईमेल तुरंत दिया जाता है, इनबॉक्स फिर नहीं खुलता), फिर प्रोवाइडर के पास इनबॉक्स फिर खोला जाता है — बिना शुल्क वाली विंडो में इंतज़ार 20 मिनट के लिए फिर शुरू होता है; विंडो के बाहर इंतज़ार की अंतिम समय-सीमा (listenUntil) वही रहती है और कोई शुल्क नहीं कटता। जवाब में refreshed (true = अभी फिर खोला गया) और refreshAvailableAt (unix सेकंड; इससे पहले दोबारा रीफ़्रेश सिर्फ़ ईमेल जाँचता है; null = अभी कर सकते हैं) जुड़ते हैं। दूसरे warehouse: कोई असर नहीं (refreshed = false)। refresh न भेजें तो कॉल पहले जैसा ही चलता है।
पैरामीटर| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
id | string | हाँ | ऑर्डर ID (orderId) — कोई भी warehouse |
confirmFee | boolean | नहीं | true = आप एक और कोड विंडो खोलने के लिए nextCodeFee.feePriceVnd चुकाने को राज़ी हैं। feePriceVnd = 0 होने पर ज़रूरी नहीं। |
refresh | boolean | नहीं | true = warehouse 2, ऑर्डर नए कोड का इंतज़ार कर रहा है (listening = true) पर कोड नहीं आ रहा: प्रोवाइडर के पास इनबॉक्स अभी फिर खोलें (इंतज़ार रीफ़्रेश करें) — पुराना इंतज़ार प्रोवाइडर की तरफ़ ईमेल लेना बंद कर चुका हो सकता है। मुफ़्त; हर ऑर्डर पर 5 सेकंड में अधिकतम एक बार। ऑर्डर इंतज़ार में नहीं ⇒ सामान्य कॉल जैसा। |
curl
Python
Node.js
# बिना शुल्क (nextCodeFee null है या feePriceVnd = 0 — हर warehouse, सिवाय warehouse 2 के जिसकी बिना शुल्क वाली विंडो खत्म हो चुकी है): confirmFee की ज़रूरत नहीं
curl -X POST "https://otpgmail.net/v1/orders/ORDER_ID/next-code" \
-H "Authorization: Bearer og_xxx..."
# बिना शुल्क वाली विंडो के बाद warehouse 2: nextCodeFee.feePriceVnd चुकाने के लिए confirmFee = true भेजें
curl -X POST "https://otpgmail.net/v1/orders/ORDER_ID/next-code" \
-H "Authorization: Bearer og_xxx..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"confirmFee":true}'{
"success": true,
"data": {
"order": {
"orderId": "ghi789rst",
"service": "dr",
"domain": "gmail.com",
"email": "[email protected]",
"status": "completed",
"price": 350,
"otp": [
{
"code": "482913",
"receivedAt": 1753268300
}
],
"codeDeadlineAt": 1753269700,
"rentExpiresAt": 1753354200,
"createdAt": 1753267800,
"warehouse": 2,
"nextCodeFee": {
"feePriceVnd": 0,
"freeUntil": 1753311000,
"hardUntil": 1753354200,
"paidPct": 50,
"freeHours": 6
},
"listening": true,
"listenUntil": 1753269500,
"nextCodeBlocked": false,
"nextCodeBlockReason": null
},
"message": "Another code window is open — waiting for a new code",
"listening": true,
"listenUntil": 1753269500,
"reordered": true
}
}संभावित एरर: UNAUTHORIZED, NOT_FOUND, VALIDATION_ERROR, NEXT_CODE_FEE_CONFIRM, INSUFFICIENT_BALANCE, EMAIL_BANNED, ORDER_EXPIRED, ORDER_NOT_CANCELLABLE, PROVIDER_ERROR, DUPLICATE_REQUEST, MAINTENANCEएक कॉल में कई ऑर्डर का स्टेटस
जो रीसेलर और बॉट बहुत सारे इनबॉक्स किराये पर लेते हैं, उन्हें हर ऑर्डर के लिए अलग
GET /v1/orders/{id} नहीं भेजना चाहिए: POST /v1/orders/status उन्हीं ऑर्डर ऑब्जेक्ट के साथ एक कॉल में 100 तक ऑर्डर पढ़ता है, और GET /v1/orders सेव किए डेटा से आपके ऑर्डर की सूची देता है।POST /v1/orders/statusसे हर 3–5 सेकंड में poll करें, हर कॉल में 100 तक ऑर्डर ID — हर कॉल रेट लिमिट में एक ही अनुरोध गिनी जाती है।- हर कॉल में सिस्टम सूची के अधिकतम 20 खुले ऑर्डर के लिए प्रोवाइडर से जाँच करता है (पहले वे जो पहले कोड का इंतज़ार कर रहे हैं, फिर वे जिनकी सबसे लंबे समय से जाँच नहीं हुई) और बाकी को सेव किए डेटा से लौटाता है; उनकी जाँच अगली कॉल में होती है। एक कॉल लगभग 3 सेकंड में जवाब देती है।
- ऑर्डर फ़ाइनल होते ही उसे अपनी सूची से हटा दें: cancelled (रिफ़ंड हो गया), या completed जब आपको और कोड नहीं चाहिए।
- जो ID मौजूद नहीं हैं या किसी दूसरे अकाउंट के हैं, वे
missingमें लौटते हैं (404 नहीं) — उन्हें भी हटा दें। - रीस्टार्ट के बाद
GET /v1/orders?status=waiting_codeसे सभी खुले ऑर्डर वापस लें (nextCursorके साथ आगे बढ़ें), फिरPOST /v1/orders/statusसे poll जारी रखें।
POST/v1/orders/status
एक कॉल में आपके 100 तक ऑर्डर लौटाता है। हर एलिमेंट ठीक वही है जो उस ऑर्डर के लिए GET /v1/orders/{id} लौटाता है (status, सभी मिले कोड के साथ otp[], warehouse…)। कई खुले ऑर्डर एक साथ poll करने के लिए इसका इस्तेमाल करें।
data, ids का क्रम बनाए रखता है; दोहराए गए ID अनदेखे किए जाते हैं। जो ID मौजूद नहीं हैं या किसी दूसरे अकाउंट के हैं, वे missing में आते हैं (404 नहीं)। खुले ऑर्डर के लिए सिस्टम GET /v1/orders/{id} की तरह ही प्रोवाइडर से जाँच करता है, पर एक कॉल में अधिकतम 20 ऑर्डर के लिए — पहले वे जो पहले कोड का इंतज़ार कर रहे हैं, फिर वे जिनकी सबसे लंबे समय से जाँच नहीं हुई — और बाकी को सेव किए डेटा से लौटाता है (उनकी जाँच अगली कॉल में होती है); एक कॉल लगभग 3 सेकंड में जवाब देती है। कितने भी ID हों, एक कॉल रेट लिमिट में एक ही अनुरोध गिनी जाती है। 100 से ज़्यादा ID, खाली सूची या ऐसे ID जो string नहीं हैं ⇒ 400 VALIDATION_ERROR।
पैरामीटर| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
ids | string[] | हाँ | ऑर्डर ID (orderId) — हर कॉल में 1 से 100 |
curl
Python
Node.js
# जिन ऑर्डर का आप इंतज़ार कर रहे हैं उनके ID (POST /v1/orders से मिला orderId) — हर कॉल में 100 तक
curl -X POST "https://otpgmail.net/v1/orders/status" \
-H "Authorization: Bearer og_xxx..." \
-H "Content-Type: application/json" \
-d '{"ids":["ORDER_ID_1","ORDER_ID_2"]}'{
"success": true,
"data": [
{
"orderId": "abc123xyz",
"service": "ig",
"domain": "gmail.com",
"email": "[email protected]",
"status": "completed",
"price": 1060,
"otp": [
{
"code": "123456",
"receivedAt": 1753268500
}
],
"codeDeadlineAt": 1753270000,
"rentExpiresAt": 1753356400,
"createdAt": 1753268200,
"warehouse": 1,
"nextCodeFee": null,
"listening": false,
"listenUntil": null,
"nextCodeBlocked": false,
"nextCodeBlockReason": null
},
{
"orderId": "jkl012mno",
"service": "ig",
"domain": "gmail.com",
"email": "[email protected]",
"status": "waiting_code",
"price": 1060,
"otp": [],
"codeDeadlineAt": 1753270001,
"rentExpiresAt": 1753356401,
"createdAt": 1753268201,
"warehouse": 1,
"nextCodeFee": null,
"listening": false,
"listenUntil": null,
"nextCodeBlocked": false,
"nextCodeBlockReason": null
}
],
"missing": [
"zzz999qqq"
]
}संभावित एरर: UNAUTHORIZED, VALIDATION_ERROR, RATE_LIMITEDGET/v1/orders
आपके ऑर्डर की सूची, सबसे नया पहले, सिर्फ़ सेव किए डेटा से — यह नए कोड के लिए प्रोवाइडर से नहीं पूछता (यह काम POST /v1/orders/status करता है)। स्टेटस और बनने के समय से फ़िल्टर करें; nextCursor से पेज बदलें।
अगला पेज पाने के लिए nextCursor को cursor के रूप में भेजें; nextCursor = null ⇒ आखिरी पेज। पेज कभी किसी ऑर्डर को दोहराते या छोड़ते नहीं, भले ही एक ही सेकंड में कई ऑर्डर बने हों। आंतरिक स्टेटस कभी सूची में नहीं आते (सिर्फ़ waiting_code, completed, cancelled और queued)। बॉट रीस्टार्ट होने के बाद: GET /v1/orders?status=waiting_code&limit=200, nextCursor के साथ आगे बढ़ें, फिर उन ऑर्डर को POST /v1/orders/status से poll करें।
पैरामीटर| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
status | string | नहीं | सिर्फ़ यह स्टेटस: waiting_code | completed | cancelled | queued (न भेजें ⇒ सभी) |
since | number | नहीं | सिर्फ़ वे ऑर्डर जो इस unix समय (सेकंड) पर या उसके बाद बने |
limit | number | नहीं | हर पेज में ऑर्डर: 1–200 (डिफ़ॉल्ट 50) |
cursor | string | नहीं | पिछले पेज का nextCursor, बिना बदले |
curl
Python
Node.js
# रीस्टार्ट के बाद: वे सभी ऑर्डर पेज-दर-पेज इकट्ठा करें जो अभी कोड का इंतज़ार कर रहे हैं
curl "https://otpgmail.net/v1/orders?status=waiting_code&limit=200" \
-H "Authorization: Bearer og_xxx..."{
"success": true,
"data": [
{
"orderId": "jkl012mno",
"service": "ig",
"domain": "gmail.com",
"email": "[email protected]",
"status": "waiting_code",
"price": 1060,
"otp": [],
"codeDeadlineAt": 1753270001,
"rentExpiresAt": 1753356401,
"createdAt": 1753268201,
"warehouse": 1,
"nextCodeFee": null,
"listening": false,
"listenUntil": null,
"nextCodeBlocked": false,
"nextCodeBlockReason": null
},
{
"orderId": "abc123xyz",
"service": "ig",
"domain": "gmail.com",
"email": "[email protected]",
"status": "waiting_code",
"price": 1060,
"otp": [],
"codeDeadlineAt": 1753270000,
"rentExpiresAt": 1753356400,
"createdAt": 1753268200,
"warehouse": 1,
"nextCodeFee": null,
"listening": false,
"listenUntil": null,
"nextCodeBlocked": false,
"nextCodeBlockReason": null
}
],
"nextCursor": "1753268200:abc123xyz"
}संभावित एरर: UNAUTHORIZED, VALIDATION_ERROR, RATE_LIMITEDWarehouse
हर
offers[] एंट्री एक ऑफ़र है = (सर्विस, warehouse, इनबॉक्स टाइप)। सिर्फ़ वही warehouse दिखते हैं जो अभी बेच रहे हैं; जिस warehouse का स्टॉक कुछ देर के लिए खत्म है वह stock = 0 के साथ लिस्ट में रहता है। Warehouse के नंबर तय हैं: 1, 2, 3, 4 — ऑर्डर बनाते समय warehouse पैरामीटर में वही नंबर भेजें।मौजूदा क्लाइंट को कोई बदलाव नहीं करना है।
warehouse न भेजें ⇒ पहले जैसा ही व्यवहार (warehouse 1: 25 मिनट का इंतज़ार, सर्विस एक से ज़्यादा कोड भेजे तो अतिरिक्त कोड 24 घंटे की ऑर्डर अवधि में अपने-आप आते हैं); 0 भेजें ⇒ स्टॉक में उपलब्ध सबसे कम कीमत वाला warehouse; 99 भेजें ⇒ ऑटोमैटिक warehouse, एक खत्म होने पर अगले पर जाना (ठीक नीचे देखें); हर मौजूदा फ़ील्ड जैसा है वैसा ही रहता है — सिर्फ़ नए फ़ील्ड जुड़ते हैं (offers[], warehouse, nextCodeFee, listening, nextCodeBlocked…)।ऑटोमैटिक warehouse: warehouse = 99 (जिन सर्विस का स्टॉक अक्सर खत्म होता है उनके लिए सुझाया गया)
offers[] के फ़ील्ड"warehouse": 99 भेजें तो सिस्टम स्टॉक में उपलब्ध सबसे कम कीमत वाले warehouse से किराए पर लेता है; अगर वह warehouse स्टॉक से बाहर है या फेल हो रहा है, तो उसी कॉल में अगले पर चला जाता है। उन सर्विस के लिए सबसे अच्छा जिनका स्टॉक अक्सर खत्म होता है, जैसे Facebook और Instagram — आपके बॉट को अब offers[] पढ़कर हर warehouse पर अलग-अलग रिट्राई नहीं करना पड़ता।- आज़माने का क्रम: कीमत कम से ज़्यादा (जैसे 1,500 → 1,600 → 1,700 VND); कीमत बराबर ⇒ छोटा warehouse नंबर पहले।
- जिन warehouse का स्टॉक शून्य बताया गया है (
offers[]मेंstock= 0) उन्हें कभी कॉल नहीं किया जाता — समय बर्बाद नहीं होता। - मौजूदा warehouse का स्टॉक खत्म हो या वह फेल हो, तो अगले पर जाता है (
OUT_OF_STOCK,NO_MAILS_AVAILABLE,WAREHOUSE_UNAVAILABLE,PROVIDER_ERROR)। - दूसरे एरर तुरंत लौटा दिए जाते हैं, अगला warehouse आज़माए बिना:
INSUFFICIENT_BALANCE,WAITING_LIMIT_REACHED,QUANTITY_EXCEEDED,MAINTENANCE,SERVICE_DISABLED,DOMAIN_UNAVAILABLE… quantity> 1: अगर पहले warehouse में कमी पड़ जाए, तो बाकी अगले से आता है — ऑर्डर कई warehouse में बँट सकते हैं; हर ऑर्डर में उस warehouse काwarehouseऔरpriceहोता है जिसने उसे जारी किया (और वह उसी warehouse के कोड नियमों पर चलता है)।- अगर हर warehouse आज़माया जा चुका हो और कोई इनबॉक्स किराए पर न मिल सका ⇒
ALL_WAREHOUSES_EXHAUSTED(HTTP 409, कुछ नहीं कटा) — बाद में फिर कोशिश करें। अगर सिर्फ़ कुछ इनबॉक्स मिले, तो उन ऑर्डर के साथ 200 मिलता है।
curl
Python
Node.js
# warehouse: 99 — स्टॉक में उपलब्ध सबसे कम कीमत वाला warehouse; स्टॉक खत्म या फेल होने पर ⇒ अपने-आप अगला warehouse
curl -X POST "https://otpgmail.net/v1/orders" \
-H "Authorization: Bearer og_xxx..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"service":"fb","quantity":1,"domain":"gmail.com","warehouse":99}'¹ जो सर्विस सिर्फ़ अपने इन्वेंटरी से बिकती हैं, जैसे Cointiply (
nextCodeFee — और कोड का शुल्क (warehouse 2 और 3 के ऑर्डर)provider = "inventory", rules.cancellable = false), वे rules का पालन करती हैं: rules.windowMinutes मिनट में अधिकतम rules.maxCodes ईमेल, कैंसल नहीं, और अगर समय खत्म होने तक कोई ईमेल न आए तो रिफंड नहीं।GET /v1/orders/{id} और हर ऑर्डर रिस्पॉन्स में शामिल; warehouse 1 और 4 के ऑर्डर के लिए null (और कोड बिना शुल्क)। Warehouse 2: एक और कोड चाहिए तो POST /v1/orders/{id}/next-code कॉल करें — अगर feePriceVnd 0 से ज़्यादा है तो confirmFee = true भेजना ज़रूरी है। Warehouse 3 (सामान्य सर्विस): बिना शुल्क वाली विंडो खत्म होने पर feePriceVnd उसी इनबॉक्स को दोबारा किराए पर लेने (rerent) की कीमत है।curl
Python
Node.js
# warehouse: 0 | 1–4 | 99 (वैकल्पिक — पहले की तरह warehouse 1 के लिए इसे न भेजें; 0 = स्टॉक में उपलब्ध सबसे कम कीमत वाला warehouse; 99 = ऑटोमैटिक, एक खत्म होने पर अगले पर जाता है; GET /v1/services में offers[] देखें)
curl -X POST "https://otpgmail.net/v1/orders" \
-H "Authorization: Bearer og_xxx..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"service":"dr","quantity":1,"domain":"gmail.com","warehouse":2}'{
"success": true,
"data": {
"orderId": "ghi789rst",
"service": "dr",
"domain": "gmail.com",
"email": "[email protected]",
"status": "completed",
"price": 350,
"otp": [
{
"code": "482913",
"receivedAt": 1753268300
}
],
"codeDeadlineAt": 1753269700,
"rentExpiresAt": 1753354200,
"createdAt": 1753267800,
"warehouse": 2,
"nextCodeFee": {
"feePriceVnd": 175,
"freeUntil": 1753289400,
"hardUntil": 1753354200,
"paidPct": 50,
"freeHours": 6
},
"listening": false,
"listenUntil": null,
"nextCodeBlocked": false,
"nextCodeBlockReason": null
}
}लॉट में किराया (batches)
लॉट वेब पर खरीदे जाते हैं (लॉट में किराया पेज) — API से आप लॉट की लिस्ट देख और कोड पढ़ सकते हैं। ईमेल डोमेन से warehouse तय होता है: Gmail = Warehouse 1, iCloud = Warehouse 3 (प्राइवेट इनबॉक्स)।
- लॉट खरीद से 24 घंटे तक रखा जाता है — उस दौरान कोड बिना शुल्क पढ़ें, कोड की संख्या की कोई सीमा नहीं।
- जिन इनबॉक्स पर कोड न आए उनका रिफंड नहीं होता; सिर्फ़ संख्या में कमी का (अपने-आप) रिफंड होता है।
- Warehouse 1 (Gmail): हर इनबॉक्स का एक
proxyUrlहै —GETकरने पर बिना API key के{"status":1,"code":"482913","all_codes":[...]}मिलता है (लिंक ही गुप्त चीज़ है — इसे निजी रखें)। नीचे का code endpoint भी काम करता है। - Warehouse 3 (iCloud):
proxyUrl=null— कोड नीचे के endpoint से पढ़ें याreadUrl(वेब पेज) खोलें। हर इनबॉक्स उस सर्विस के लिए आपके अकाउंट से जुड़ा रहता है; एक्सपायर होने के बाद भी आप उसे वेब पर फिर किराए पर ले सकते हैं। - जिन ईमेल से कोड नहीं निकाला जा सकता (वेलकम ईमेल, न्यूज़लेटर…) वे
isRaw: trueके साथcodeमें जस के तस लौटते हैं (HTML या टेक्स्ट, 20,000 अक्षर तक)।
GET/v1/batches
आपके लॉट, सबसे नया पहले (page / pageSize से पेज, 100 तक)। हर लॉट में warehouse (1 = Gmail, 3 = iCloud), status (active | expired | failed), expiresAt, codeCount और readUrl होते हैं।
पैरामीटर| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
page | number | नहीं | पेज (डिफ़ॉल्ट 1) |
pageSize | number | नहीं | प्रति पेज लॉट (डिफ़ॉल्ट 20, अधिकतम 100) |
curl
Python
Node.js
curl "https://otpgmail.net/v1/batches?page=1&pageSize=20" \
-H "Authorization: Bearer og_xxx..."{
"success": true,
"data": {
"items": [
{
"id": "k3v9m2x7q1w8e5r4",
"serviceCode": "lf",
"serviceName": "Tiktok",
"domain": "icloud.com",
"warehouse": 3,
"status": "active",
"countRequested": 3,
"countReceived": 3,
"countDuplicate": 0,
"countCharged": 3,
"unitPriceVnd": 600,
"quotedVnd": 1800,
"chargedVnd": 1800,
"refundVnd": 0,
"holdHours": 24,
"expiresAt": 1753354200,
"createdAt": 1753267800,
"readUrl": "https://otpgmail.net/app/batch/k3v9m2x7q1w8e5r4",
"codeCount": 1,
"rerentPriceVnd": null
}
],
"total": 1,
"page": 1,
"pageSize": 20
}
}संभावित एरर: UNAUTHORIZEDGET/v1/batches/{id}
एक लॉट उसके mails[] के साथ — कोड पढ़ने के लिए हर इनबॉक्स की id लें।
Gmail लॉट (warehouse 1): हर इनबॉक्स का proxyUrl आपकी स्क्रिप्ट में ठीक पहले की तरह चलता है। iCloud लॉट (warehouse 3): proxyUrl = null, कोड नीचे वाले endpoint से पढ़ें। एक्सपायर हुए iCloud लॉट में rerentPriceVnd होता है — एक इनबॉक्स को अलग से फिर किराए पर लेने की कीमत (यह वेब पर होता है)।
पैरामीटर| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
id | string | हाँ | लॉट ID (लॉट में किराया पेज और readUrl में दिखती है) |
curl
Python
Node.js
curl "https://otpgmail.net/v1/batches/BATCH_ID" \
-H "Authorization: Bearer og_xxx..."{
"success": true,
"data": {
"id": "k3v9m2x7q1w8e5r4",
"serviceCode": "lf",
"serviceName": "Tiktok",
"domain": "icloud.com",
"warehouse": 3,
"status": "active",
"countRequested": 3,
"countReceived": 3,
"countDuplicate": 0,
"countCharged": 3,
"unitPriceVnd": 600,
"quotedVnd": 1800,
"chargedVnd": 1800,
"refundVnd": 0,
"holdHours": 24,
"expiresAt": 1753354200,
"createdAt": 1753267800,
"readUrl": "https://otpgmail.net/app/batch/k3v9m2x7q1w8e5r4",
"codeCount": 1,
"rerentPriceVnd": null,
"mails": [
{
"id": 812,
"email": "[email protected]",
"url": "https://otpgmail.net/app/batch/k3v9m2x7q1w8e5r4",
"proxyUrl": null,
"readUrl": "https://otpgmail.net/app/batch/k3v9m2x7q1w8e5r4",
"fresh": true,
"codeCount": 1,
"lastCode": "482913",
"lastCodeAt": 1753268500,
"lastIsRaw": false,
"checkedAt": 1753268507
}
]
}
}संभावित एरर: UNAUTHORIZED, NOT_FOUNDGET/v1/batches/{id}/mails/{mailId}/codes
लॉट के एक इनबॉक्स के कोड पढ़ें: अगर इनबॉक्स की बारी हो तो सिस्टम प्रोवाइडर को जाँचता है, फिर मिला हुआ हर कोड लौटाता है, सबसे पुराना पहले — सबसे नया कोड codes[] में आखिरी होता है।
इंतज़ार करते समय हर 5–10 सेकंड में poll करें (इससे ज़्यादा बार कॉल करने पर सिर्फ़ सेव किया हुआ डेटा लौटता है — polledAt नहीं बदलता)। जिन ईमेल से कोड नहीं निकाला जा सका वे isRaw: true के साथ code में जस के तस आते हैं। एक्सपायर हुए लॉट अब भी अपने सेव किए कोड लौटाते हैं पर उन्हें और जाँचा नहीं जाता।
पैरामीटर| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
id | string | हाँ | लॉट ID |
mailId | number | हाँ | इनबॉक्स ID (mails[].id) |
poll | 0 | 1 | नहीं | 0 = सिर्फ़ सेव किए कोड पढ़ें, प्रोवाइडर को न जाँचें (डिफ़ॉल्ट 1) |
curl
Python
Node.js
# इंतज़ार करते समय हर 5–10 सेकंड में फिर कॉल करें; सबसे नया कोड codes[] में आखिरी होता है
curl "https://otpgmail.net/v1/batches/BATCH_ID/mails/MAIL_ID/codes" \
-H "Authorization: Bearer og_xxx..."{
"success": true,
"data": {
"mailId": 812,
"codes": [
{
"code": "482913",
"receivedAt": 1753268500,
"isRaw": false
}
],
"polledAt": 1753268507,
"mail": {
"id": 812,
"email": "[email protected]",
"url": "https://otpgmail.net/app/batch/k3v9m2x7q1w8e5r4",
"proxyUrl": null,
"readUrl": "https://otpgmail.net/app/batch/k3v9m2x7q1w8e5r4",
"fresh": true,
"codeCount": 1,
"lastCode": "482913",
"lastCodeAt": 1753268500,
"lastIsRaw": false,
"checkedAt": 1753268507
}
}
}संभावित एरर: UNAUTHORIZED, NOT_FOUND, RATE_LIMITEDBuy live Gmail accounts (2 warehouses)
Buy short-lived Gmail accounts outright: you are charged when you order and the accounts arrive within seconds. There are two mail-shop warehouses (numbered separately from the OTP-rental warehouses 1–4), each with ONE price for any quantity. Prices returned by the API are YOUR account's prices (custom price if the admin set one) — exactly what you are charged.
Warehouses- Warehouse 1 (
gm_cookie) के अकाउंट बिना रिकवरी ईमेल के आते हैं — आपको ईमेल, पासवर्ड, कुकीज़ और इनबॉक्स लिंक (inboxUrl/inboxJsonUrl) मिलते हैं, इससे ज़्यादा कुछ नहीं। - लॉगिन का सुझाया गया तरीका: कुकीज़ इंपोर्ट करें (
cookies, JSON) — किसी कुकी-इंपोर्ट एक्सटेंशन से या अपने antidetect ब्राउज़र के कुकी इंपोर्ट से — फिर Gmail खोलें: सेशन पहले से लॉग-इन रहता है, आम तौर पर न पासवर्ड पूछा जाता है न वेरिफ़िकेशन। - सिर्फ़ कोड या ईमेल चाहिए? उन्हें
inboxUrl(वेब पेज) याinboxJsonUrl(JSON) से पढ़ें — न API key चाहिए, न Google लॉगिन। - नए डिवाइस या IP पर पासवर्ड से लॉगिन करने पर Google वेरिफ़िकेशन (रिकवरी ईमेल, फ़ोन या कोड) मांग सकता है — इन अकाउंट के पास इसे पार करने का कोई ज़रिया नहीं, इसलिए कुकीज़ या इनबॉक्स लिंक इस्तेमाल करें।
- आगे बेच रहे हैं? अपने ग्राहकों को कुकीज़ और इनबॉक्स लिंक दोनों दें — .txt डाउनलोड (
GET /v1/mail-shop/orders/{id}/download) में एक लाइन मेंemail|password|cookies|inboxUrlहोता है — और उन्हें बताएं कि पासवर्ड से नहीं, कुकीज़ से लॉगिन करें। - Warehouse 2 (
gm_login) के अकाउंट इसकी जगह क्विक लॉगिन लिंक (loginUrl) के साथ आते हैं — लॉगिन के लिए इसे कंप्यूटर के ब्राउज़र में खोलें।
- See warehouses & prices:
GET /v1/mail-shop/products⇒products[](per warehouse:priceVnd,stock,available,maxQty) +auto(warehouse 99:order,priceVnd). To see the total first, callGET /v1/mail-shop/quote. - Buy:
POST /v1/mail-shop/orderswith{"warehouse": 1 | 2 | 99, "quantity": N}+ headerIdempotency-Key(a new UUID per purchase). The response is the order, usually alreadycompletedwithitems[]. - Get the accounts: read
items[](table below) or download the TXTGET /v1/mail-shop/orders/{id}/download.status=pending⇒ pollGET /v1/mail-shop/orders/{id}every 5 seconds untilcompleted/partial/failed.
curl
Python
Node.js
# 1) warehouses, your prices, stock
curl "https://otpgmail.net/v1/mail-shop/products" -H "Authorization: Bearer og_xxx..."
# 2) buy (warehouse 1 | 2 | 99) — a NEW Idempotency-Key per purchase
curl -X POST "https://otpgmail.net/v1/mail-shop/orders" \
-H "Authorization: Bearer og_xxx..." -H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" --max-time 60 \
-d '{"warehouse":99,"quantity":2}'
# 3) status "pending"? read the order again (or download the .txt)
curl "https://otpgmail.net/v1/mail-shop/orders/ORDER_ID" -H "Authorization: Bearer og_xxx..."GET {inboxJsonUrl} (= inboxUrl + ?json) returns the same JSON as GET /api/mailbox/{code}: email, letters[] (≤ max latest emails: from, subject, receivedAt, code — extracted code / link, content — sanitized HTML), total, etag, nextAt. No API key needed (the code in the link is the key — keep it private), CORS is open. Add &max=20|50|100|200 for more emails (default 10), &etag={previous etag} ⇒ unchanged emails come back as empty letters + unchanged: true. Reading one link faster than every 10 seconds ⇒ 429 (retryAfter); link off / wrong / expired ⇒ 404; account locked ⇒ 410.curl "https://otpgmail.net/mail/Q7xK2mP9vL4tR8wN3cB6yH1d?json&max=20"{
"success": true,
"data": {
"email": "[email protected]",
"letters": [
{
"key": "h:9f2c4e1a7b3d5c80",
"from": "Instagram [email protected]",
"subject": "350038 is your Instagram code",
"receivedAt": 1760000520,
"code": "350038",
"content": "<html><body><p>Enter this confirmation code in the app: 350038</p></body></html>"
}
],
"max": 10,
"total": 8,
"fetchedAt": 1760000530,
"cached": false,
"etag": "f1c2a9d4e0b37a65",
"unchanged": false,
"nextAt": 1760000540,
"expiresAt": 1762592400,
"serverTime": 1760000530
}
}Read the Vinted OTP code (otpUrl)A warehouse-2 account with
otpUrl ⇒ open it in a browser to see the latest Vinted code (the page refreshes itself); GET {otpUrl}?json returns {status, code, service, email, checkedAt, retryAfter}: status = waiting (no code yet — ask again after retryAfter seconds) · ok (code = the latest code) · dead (codes can no longer be read for this account) · error (temporarily unreadable — ask again). No API key needed (the code in the link is the key — keep it private), CORS is open; the server reads the source at most every few seconds per account; more than 120 calls / minute / IP ⇒ 429.curl "https://otpgmail.net/api/mail-shop/otp/p3x9k2m7q1w8e5r4.2.Zx8Kq2Lm4Np6Rt0Vw3Yb5c?json"{
"success": true,
"data": {
"status": "ok",
"code": "4829",
"service": "vinted",
"email": "[email protected]",
"checkedAt": 1760000530,
"retryAfter": 5
}
}The 2FA code (twoFaUrl)Some warehouse-1 accounts have 2-step verification (2FA) on — a password sign-in makes Google ask for a 6-digit code.
GET {twoFaUrl} (or open it in a browser) returns text/plain with JUST the current 6 digits (no newline), a Refresh header = seconds until the next code + 1 (browsers reload by themselves), Cache-Control: no-store, open CORS — you can hand the link to your customers. Account without 2FA ⇒ 404 no 2fa; wrong / off / expired link ⇒ 404 not found; locked account ⇒ 410 gone; too fast / source hiccup ⇒ 429 / 502 retry (Retry-After header). With an API key: GET /v1/mail-shop/orders/{id}/items/{lineNo}/2fa ⇒ {none, code, expiresIn}. The server caches the code until it expires. The .txt file (GET /v1/mail-shop/orders/{id}/download): add ?twofa=1 ⇒ a last twoFaUrl column (off by default — the old layout is unchanged).curl "https://otpgmail.net/2fa/Q7xK2mP9vL4tR8wN3cB6yH1d"
# 424819Order statuses- Money:
chargedVnd= Σroute[].quantity×unitPriceVnd(a 99 order split across warehouses ⇒ two legs inroute). Shortfalls are refunded automatically (refundVnd). Delivered accounts are not refunded — the only warranty is the warehouse'sterms(read them first). - Idempotency-Key is required (400 without it): retrying with the SAME key after a timeout returns the same order and charges nothing more; a new key buys again. Use a client timeout of at least 60 seconds.
- Limits: at most 500 accounts per order (and the warehouse's
maxQty), 10 purchases per minute for your account (web + API share it), 180 inbox reads per hour. Above ⇒ 429RATE_LIMITED. - Common errors:
MAILSHOP_OUT_OF_STOCK409 (details.stock= how many you can buy now) ·MAILSHOP_QTY_LIMIT400 (details.max) ·INSUFFICIENT_BALANCE402 ·MAILSHOP_DISABLED503 (warehouse / section paused) ·MAILSHOP_SUPPLIER_ERROR502 (the source refused at once — a failed order was recorded and refunded,details.orderId) ·VALIDATION_ERROR400 (warehouse not 1 | 2 | 99, warehouse and product disagree, missing Idempotency-Key…). - Terms (warranty only for the first sign-in within 2 hours, accounts last ~6–24 hours) are in each warehouse's
terms; the API does not ask you to accept them (the web asks once). API orders show up in your web history (channel=api) and vice versa.
GET/v1/mail-shop/products
The two mail-shop warehouses + automatic warehouse 99. products[]: warehouse (1 | 2), code (gm_cookie | gm_login), delivers (fields of every account), priceVnd (YOUR price), listPriceVnd (list price), stock, available, maxQty (most one order can take now). auto: order (the order warehouse 99 buys in), priceVnd (cheapest warehouse), available.
Warehouse 1 stock = what the source publishes (refreshed every minute; the source checks accounts are live at purchase time, so you may get fewer — the shortfall is refunded). Warehouse 2 = a reference number from a source sharing the same stock, may be off by a few (null = could not be read — just buy); a shortfall becomes a partial order with the rest refunded. available = false ⇒ do not buy from that warehouse (out of stock / paused). Prices can change — read the catalog again before a large purchase.
उदाहरणcurl
Python
Node.js
curl "https://otpgmail.net/v1/mail-shop/products" \
-H "Authorization: Bearer og_xxx..."{
"success": true,
"data": {
"products": [
{
"warehouse": 1,
"code": "gm_cookie",
"name": "Short-lived live Gmail — with cookies + inbox link",
"description": "Short-lived personal Gmail account. You get the email · password · login cookies · an inbox link (add ?json to read the emails as JSON).",
"terms": "• Warranty covers ONLY the first successful sign-in, within 2 hours of purchase.\n• These Gmail accounts typically last 6–24 hours: use them right after purchase.",
"delivers": [
"email",
"password",
"cookies",
"inboxUrl",
"inboxJsonUrl"
],
"priceVnd": 3300,
"listPriceVnd": 3300,
"stock": 1840,
"available": true,
"maxQty": 500
},
{
"warehouse": 2,
"code": "gm_login",
"name": "Short-lived live Gmail — with a quick login link",
"description": "Short-lived personal Gmail account that has been used on a few services. You get the email · password · a quick login link.",
"terms": "• Warranty covers ONLY the first successful sign-in, within 2 hours of purchase.\n• Sign in with the link in a DESKTOP BROWSER.",
"delivers": [
"email",
"password",
"loginUrl"
],
"priceVnd": 6000,
"listPriceVnd": 6000,
"stock": 141,
"available": true,
"maxQty": 100
}
],
"auto": {
"warehouse": 99,
"priceVnd": 3300,
"available": true,
"order": [
1,
2
]
}
}
}संभावित एरर: UNAUTHORIZEDGET/v1/mail-shop/quote
Call quote to see the total first (nothing is reserved). Warehouse 99 ⇒ route[] = planned split by known stock; available = false ⇒ that quantity cannot be bought right now.
पैरामीटर| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
warehouse | 1 | 2 | 99 | नहीं | Mail-shop warehouse: 1 = email + password + cookies + inbox link · 2 = email + password + login link · 99 = automatic, cheapest first. Send warehouse OR product |
product | string | नहीं | Instead of warehouse: gm_cookie (= warehouse 1) | gm_login (= warehouse 2) |
quantity | number | नहीं | Number of accounts (default 1) |
curl
Python
Node.js
curl "https://otpgmail.net/v1/mail-shop/quote?warehouse=99&quantity=10" \
-H "Authorization: Bearer og_xxx..."{
"success": true,
"data": {
"warehouse": 99,
"quantity": 10,
"unitPriceVnd": 3300,
"totalVnd": 38400,
"available": true,
"stock": null,
"maxQty": 500,
"route": [
{
"warehouse": 1,
"quantity": 8,
"unitPriceVnd": 3300
},
{
"warehouse": 2,
"quantity": 2,
"unitPriceVnd": 6000
}
]
}
}संभावित एरर: UNAUTHORIZED, VALIDATION_ERROR, MAILSHOP_PRODUCT_NOT_FOUNDPOST/v1/mail-shop/orders
Buy: you are charged at once, then the system buys from the source and delivers. The response is the order — usually already completed with items[]; status = pending ⇒ poll GET /v1/mail-shop/orders/{id} every 5 seconds. The call waits up to about 16 seconds for the delivery.
Idempotency-Key is required (400 without it). Not enough stock ⇒ MAILSHOP_OUT_OF_STOCK (error.details.stock = how many you can buy now, nothing charged); over the per-order limit ⇒ MAILSHOP_QTY_LIMIT (error.details.max). 502 MAILSHOP_SUPPLIER_ERROR = the source refused at once: a failed order was recorded and fully refunded (error.details.orderId) — retry with a new key.
पैरामीटर| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
warehouse | 1 | 2 | 99 | नहीं | Mail-shop warehouse: 1 = email + password + cookies + inbox link · 2 = email + password + login link · 99 = automatic, cheapest first. Send warehouse OR product |
product | string | नहीं | Instead of warehouse: gm_cookie (= warehouse 1) | gm_login (= warehouse 2) |
quantity | number | नहीं | Number of accounts (default 1) |
Idempotency-Key | string | हाँ | Header: a new UUID for every new purchase — reuse it only to retry that same purchase |
curl
Python
Node.js
# Idempotency-Key ज़रूरी है: हर खरीद के लिए नया UUID — वही key सिर्फ़ टाइमआउट के बाद रिट्राई में दोबारा इस्तेमाल करें
# warehouse: 1 = cookies + inbox link · 2 = login link · 99 = cheapest first
curl -X POST "https://otpgmail.net/v1/mail-shop/orders" \
-H "Authorization: Bearer og_xxx..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
--max-time 60 \
-d '{"warehouse":99,"quantity":5}'{
"success": true,
"data": {
"id": "p3x9k2m7q1w8e5r4",
"requestedWarehouse": 99,
"warehouse": 1,
"productCode": "gm_cookie",
"quantity": 2,
"deliveredCount": 2,
"unitPriceVnd": 3300,
"chargedVnd": 9300,
"refundVnd": 0,
"status": "completed",
"channel": "api",
"route": [
{
"warehouse": 1,
"quantity": 1,
"unitPriceVnd": 3300
},
{
"warehouse": 2,
"quantity": 1,
"unitPriceVnd": 6000
}
],
"message": null,
"createdAt": 1760000400,
"completedAt": 1760000409,
"items": [
{
"lineNo": 1,
"warehouse": 1,
"email": "[email protected]",
"password": "Pw7Xq!k3d",
"rawLine": "[email protected]|Pw7Xq!k3d||[{\"domain\":\".google.com\",\"name\":\"SID\",\"value\":\"g.a000…\"}]",
"cookies": "[{\"domain\":\".google.com\",\"name\":\"SID\",\"value\":\"g.a000…\"}]",
"inboxUrl": "https://otpgmail.net/mail/Q7xK2mP9vL4tR8wN3cB6yH1d",
"inboxJsonUrl": "https://otpgmail.net/mail/Q7xK2mP9vL4tR8wN3cB6yH1d?json",
"twoFaUrl": "https://otpgmail.net/2fa/Q7xK2mP9vL4tR8wN3cB6yH1d",
"inboxLinkExpiresAt": 1762592400
},
{
"lineNo": 2,
"warehouse": 2,
"email": "[email protected]",
"password": "Qp9!rT2",
"rawLine": "[email protected]!rT2----no----https://login.example/google/login?uid=s2c38a3b",
"loginUrl": "https://login.example/google/login?uid=s2c38a3b",
"otpUrl": "https://otpgmail.net/api/mail-shop/otp/p3x9k2m7q1w8e5r4.2.Zx8Kq2Lm4Np6Rt0Vw3Yb5c",
"otpService": "vinted"
}
]
}
}संभावित एरर: UNAUTHORIZED, VALIDATION_ERROR, MAILSHOP_PRODUCT_NOT_FOUND, MAILSHOP_DISABLED, MAILSHOP_QTY_LIMIT, MAILSHOP_OUT_OF_STOCK, INSUFFICIENT_BALANCE, MAILSHOP_SUPPLIER_ERROR, RATE_LIMITED, DUPLICATE_REQUEST, MAINTENANCEGET/v1/mail-shop/orders
Your mail-shop orders, newest first (page / pageSize, up to 100 per page) — without items[]: fetch an order to get its accounts. Orders bought on the web are listed too (channel = web).
पैरामीटर| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
page | number | नहीं | Page (default 1) |
pageSize | number | नहीं | Orders per page (default 20, max 100) |
curl
Python
Node.js
curl "https://otpgmail.net/v1/mail-shop/orders?page=1&pageSize=20" \
-H "Authorization: Bearer og_xxx..."{
"success": true,
"data": {
"items": [
{
"id": "p3x9k2m7q1w8e5r4",
"requestedWarehouse": 99,
"warehouse": 1,
"productCode": "gm_cookie",
"quantity": 2,
"deliveredCount": 2,
"unitPriceVnd": 3300,
"chargedVnd": 9300,
"refundVnd": 0,
"status": "completed",
"channel": "api",
"route": [
{
"warehouse": 1,
"quantity": 1,
"unitPriceVnd": 3300
},
{
"warehouse": 2,
"quantity": 1,
"unitPriceVnd": 6000
}
],
"message": null,
"createdAt": 1760000400,
"completedAt": 1760000409
}
],
"total": 1,
"page": 1,
"pageSize": 20
}
}संभावित एरर: UNAUTHORIZEDGET/v1/mail-shop/orders/{id}
One order with every account delivered so far (an order still delivering already shows what has arrived). route[] = which warehouse, how many, at what price.
Poll every 5 seconds while status = pending; completed / partial / failed / refunded are final. An order of many warehouse-1 accounts (cookies) can weigh several MB — stop polling once it is final.
पैरामीटर| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
id | string | हाँ | Order ID (data.id returned by the purchase) |
curl
Python
Node.js
curl "https://otpgmail.net/v1/mail-shop/orders/ORDER_ID" \
-H "Authorization: Bearer og_xxx..."{
"success": true,
"data": {
"id": "p3x9k2m7q1w8e5r4",
"requestedWarehouse": 99,
"warehouse": 1,
"productCode": "gm_cookie",
"quantity": 2,
"deliveredCount": 2,
"unitPriceVnd": 3300,
"chargedVnd": 9300,
"refundVnd": 0,
"status": "completed",
"channel": "api",
"route": [
{
"warehouse": 1,
"quantity": 1,
"unitPriceVnd": 3300
},
{
"warehouse": 2,
"quantity": 1,
"unitPriceVnd": 6000
}
],
"message": null,
"createdAt": 1760000400,
"completedAt": 1760000409,
"items": [
{
"lineNo": 1,
"warehouse": 1,
"email": "[email protected]",
"password": "Pw7Xq!k3d",
"rawLine": "[email protected]|Pw7Xq!k3d||[{\"domain\":\".google.com\",\"name\":\"SID\",\"value\":\"g.a000…\"}]",
"cookies": "[{\"domain\":\".google.com\",\"name\":\"SID\",\"value\":\"g.a000…\"}]",
"inboxUrl": "https://otpgmail.net/mail/Q7xK2mP9vL4tR8wN3cB6yH1d",
"inboxJsonUrl": "https://otpgmail.net/mail/Q7xK2mP9vL4tR8wN3cB6yH1d?json",
"twoFaUrl": "https://otpgmail.net/2fa/Q7xK2mP9vL4tR8wN3cB6yH1d",
"inboxLinkExpiresAt": 1762592400
},
{
"lineNo": 2,
"warehouse": 2,
"email": "[email protected]",
"password": "Qp9!rT2",
"rawLine": "[email protected]!rT2----no----https://login.example/google/login?uid=s2c38a3b",
"loginUrl": "https://login.example/google/login?uid=s2c38a3b",
"otpUrl": "https://otpgmail.net/api/mail-shop/otp/p3x9k2m7q1w8e5r4.2.Zx8Kq2Lm4Np6Rt0Vw3Yb5c",
"otpService": "vinted"
}
]
}
}संभावित एरर: UNAUTHORIZED, NOT_FOUNDGET/v1/mail-shop/orders/{id}/download
The delivered accounts as .txt (text/plain), separated by |. The FIRST LINE is the column header: warehouse 1 email|password|cookies|inboxUrl · warehouse 2 email|password|loginUrl · a 99 order with both warehouses ⇒ email|password|cookies|inboxUrl|loginUrl (missing cells empty).
cookies is one-line JSON and may contain | — split email and password at the first two |, the link at the last | (with extra columns ⇒ the links after cookies at the last | separators — links never contain |; read the header line for their order). Nothing delivered yet ⇒ 409 VALIDATION_ERROR. Add <c>?otp=1</c> ⇒ warehouse 2 gets a LAST column <c>otpUrl</c> (the Vinted OTP link — empty when the account has none): email|password|loginUrl|otpUrl. Without it ⇒ exactly the columns above. Add <c>?twofa=1</c> ⇒ warehouse 1 gets a LAST column <c>twoFaUrl</c> (the 2FA link — same code as inboxUrl; GET ⇒ just the 6 digits; empty when the link is off / expired): email|password|cookies|inboxUrl|twoFaUrl. Combines with <c>otp=1</c> — fixed column order: …|loginUrl|otpUrl|twoFaUrl (a 99 order with both warehouses). Without it ⇒ the default layout above.
पैरामीटर| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
id | string | हाँ | Order ID (data.id returned by the purchase) |
curl
Python
Node.js
curl "https://otpgmail.net/v1/mail-shop/orders/ORDER_ID/download" \
-H "Authorization: Bearer og_xxx..." \
-o mail-ORDER_ID.txtemail|password|cookies|inboxUrl
[email protected]|Pw7Xq!k3d|[{"domain":".google.com","name":"SID","value":"g.a000…"}]|https://otpgmail.net/mail/Q7xK2mP9vL4tR8wN3cB6yH1dसंभावित एरर: UNAUTHORIZED, NOT_FOUND, VALIDATION_ERRORGET/v1/mail-shop/orders/{id}/items/{lineNo}/inbox
Latest emails of a WAREHOUSE-1 account (sender, subject, time, extracted code / link, sanitized full email). Without an API key: GET the account's inboxJsonUrl (same emails, JSON).
max = 10 (default) | 20 | 50 | 100 | 200 — more emails take longer (up to about a minute). Cached for 15 seconds; every real read counts toward the hourly limit. 409 VALIDATION_ERROR = a warehouse-2 account (no inbox reading); 409 PROVIDER_ERROR with details.dead = the account was locked or removed.
पैरामीटर| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
id | string | हाँ | Order ID (data.id returned by the purchase) |
lineNo | number | हाँ | Account number within the order (items[].lineNo) |
max | number | नहीं | Number of latest emails: 10 (default), 20, 50, 100 or 200 |
curl
Python
Node.js
# Warehouse 1 accounts only; max = 10 | 20 | 50 | 100 | 200
curl "https://otpgmail.net/v1/mail-shop/orders/ORDER_ID/items/1/inbox?max=20" \
-H "Authorization: Bearer og_xxx..." \
--max-time 70
# Same emails without an API key: GET the account's inboxJsonUrl
curl "https://otpgmail.net/mail/Q7xK2mP9vL4tR8wN3cB6yH1d?json&max=20"{
"success": true,
"data": {
"email": "[email protected]",
"letters": [
{
"key": "h:9f2c4e1a7b3d5c80",
"from": "Instagram [email protected]",
"subject": "350038 is your Instagram code",
"receivedAt": 1760000520,
"code": "350038",
"content": "<html><body><p>Enter this confirmation code in the app: 350038</p></body></html>"
}
],
"max": 10,
"total": 8,
"fetchedAt": 1760000530,
"cached": false
}
}संभावित एरर: UNAUTHORIZED, NOT_FOUND, VALIDATION_ERROR, RATE_LIMITED, PROVIDER_ERRORPOST/v1/mail-shop/orders/{id}/items/{lineNo}/inbox-link
Manage the inbox link (inboxUrl + inboxJsonUrl + twoFaUrl — one shared code) of a warehouse-1 account: action "regenerate" = NEW link (the old one stops working immediately; also re-enables a link you turned off), "off" = turn it off (inboxUrl / inboxJsonUrl / twoFaUrl become null). Returns the account (an element of items[]).
At most 60 changes per 10 minutes for your account.
पैरामीटर| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
id | string | हाँ | Order ID (data.id returned by the purchase) |
lineNo | number | हाँ | Account number within the order (items[].lineNo) |
action | string | हाँ | "regenerate" = new link (the old one stops working immediately) · "off" = turn the link off |
curl
Python
Node.js
# नया लिंक (पुराना तुरंत काम करना बंद कर देता है); बंद करने के लिए {"action":"off"} भेजें
curl -X POST "https://otpgmail.net/v1/mail-shop/orders/ORDER_ID/items/1/inbox-link" \
-H "Authorization: Bearer og_xxx..." \
-H "Content-Type: application/json" \
-d '{"action":"regenerate"}'{
"success": true,
"data": {
"lineNo": 1,
"warehouse": 1,
"email": "[email protected]",
"password": "Pw7Xq!k3d",
"rawLine": "[email protected]|Pw7Xq!k3d||[{\"domain\":\".google.com\",\"name\":\"SID\",\"value\":\"g.a000…\"}]",
"cookies": "[{\"domain\":\".google.com\",\"name\":\"SID\",\"value\":\"g.a000…\"}]",
"inboxUrl": "https://otpgmail.net/mail/Hn4Vw8Zr2Lk6Tq9Pm3Xs7Bd1",
"inboxJsonUrl": "https://otpgmail.net/mail/Hn4Vw8Zr2Lk6Tq9Pm3Xs7Bd1?json",
"twoFaUrl": "https://otpgmail.net/2fa/Hn4Vw8Zr2Lk6Tq9Pm3Xs7Bd1",
"inboxLinkExpiresAt": 1762592400
}
}संभावित एरर: UNAUTHORIZED, NOT_FOUND, VALIDATION_ERROR, RATE_LIMITEDGET/v1/mail-shop/orders/{id}/items/{lineNo}/status
Is a bought warehouse-1 account still alive: live = true / false, or null when it cannot be determined. Counts toward the hourly inbox-read limit.
पैरामीटर| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
id | string | हाँ | Order ID (data.id returned by the purchase) |
lineNo | number | हाँ | Account number within the order (items[].lineNo) |
curl
Python
Node.js
curl "https://otpgmail.net/v1/mail-shop/orders/ORDER_ID/items/1/status" \
-H "Authorization: Bearer og_xxx..."{
"success": true,
"data": {
"email": "[email protected]",
"live": true,
"reason": null,
"checkedAt": 1760000600
}
}संभावित एरर: UNAUTHORIZED, NOT_FOUND, VALIDATION_ERROR, RATE_LIMITED, PROVIDER_ERRORGET/v1/mail-shop/orders/{id}/items/{lineNo}/2fa
The current 2FA code (6-digit TOTP, changes every 30 seconds) of a warehouse-1 account — some warehouse-1 accounts have 2-step verification on (Google asks for a code at a password sign-in). none = true ⇒ the account has no 2FA (code / expiresIn null). expiresIn = seconds the code stays valid — ask again after that. Without an API key: GET the account's twoFaUrl (the body is just the 6 digits).
The server caches the code until it expires (every call within those 30 seconds gets the same code) — it does NOT count toward the hourly inbox-read limit. Calling too fast ⇒ 429 (retryAfterSec); a warehouse-2 account ⇒ 409; a locked account ⇒ 409 (details.dead).
पैरामीटर| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
id | string | हाँ | Order ID (data.id returned by the purchase) |
lineNo | number | हाँ | Account number within the order (items[].lineNo) |
curl
Python
Node.js
curl "https://otpgmail.net/v1/mail-shop/orders/ORDER_ID/items/1/2fa" \
-H "Authorization: Bearer og_xxx..."{
"success": true,
"data": {
"none": false,
"code": "424819",
"expiresIn": 24
}
}संभावित एरर: UNAUTHORIZED, NOT_FOUND, VALIDATION_ERROR, RATE_LIMITED, PROVIDER_ERRORऑर्डर का जीवनचक्र
ज़रूरी बातें:
- जब तक ऑर्डर waiting_code में है,
GET /v1/orders/{id}को हर 3–5 सेकंड में poll करें ताकि कोड जल्दी मिल जाए। - पहला कोड आते ही स्टेटस तुरंत completed हो जाता है।
codeDeadlineAtतक कोई कोड न आए (अधिकतम 25 मिनट; warehouse 2: 20 मिनट; warehouse 4 के कुछ स्रोतों में कम) ⇒ सिस्टम ऑर्डर कैंसल करके 100% वापस कर देता है (status = cancelled)।otp[]ऐरे सबसे पुराना पहले, सबसे नया आखिर में के क्रम में होता है। ताज़ा कोडotp[otp.length - 1]से पढ़ें (Python:otp[-1])।- completed ऑर्डर पर कोड अपने-आप आते रहते हैं:
GET /v1/orders/{id}को poll करते रहें, हर नया कोडotp[]के अंत में दिखता है। अगर सर्विस एक से ज़्यादा कोड भेजती है तो ऑर्डर की अवधि में अतिरिक्त कोड पर कुछ नहीं लगता; सीमा और समय-विंडो किराए पर लेने से पहले दिखती है (offers[]मेंmaxCodesऔरfee; warehouse 1 में इनबॉक्स आम तौर पर आखिरी कोड के बाद लगभग 25 मिनट खुला रहता है)। साफ़ तौर पर एक और कोड माँगने के लिए (जैसे साइन-अप के बाद लॉग-इन):POST /v1/orders/{id}/next-code— हर warehouse में काम करता है, और शुल्क सिर्फ़ warehouse 2 अपनी बिना शुल्क वाली विंडो के बाहर लेता है। - अगर सर्विस हर इनबॉक्स पर सिर्फ़ एक कोड की इजाज़त देती है, तो
otp[]उसी कोड पर रुक जाता है। रिस्पॉन्स सामान्य रहते हैं, कोई एरर नहीं — poll कब रोकना है यह आप तय करते हैं। otp[].codeआम तौर पर एक छोटा कोड (अंक / अक्षर) या एक लिंक होता है। जिस ईमेल से कोड नहीं निकाला जा सका (वेलकम ईमेल, न्यूज़लेटर, अजीब फ़ॉर्मेट वाला कोड…) वहotp[].codeमें पूरा का पूरा (HTML या टेक्स्ट) दिया जाता है — 80 अक्षरों से लंबा हो, उसमें लाइन-ब्रेक हो या वह HTML हो तो उसे पूरा ईमेल मानें और कोड या लिंक उसमें खुद खोजें।POST /v1/ordersप्रोवाइडर के इनबॉक्स देने का इंतज़ार करता है, इसलिए आम तौर पर ~0.3 सेकंड लेता है पर भीड़ के समय (कभी-कभार) 10 सेकंड तक लग सकता है। क्लाइंट का टाइमआउट ≈ 15 सेकंड रखें, 5 सेकंड बाद हार मानकर जल्दी रिट्राई न करें — और रिट्राई करें तो वहीIdempotency-Keyइस्तेमाल करें।- जिस ऑर्डर को कोड मिल चुका है उसे कैंसल नहीं किया जा सकता और उसका रिफंड नहीं होता — cancel कॉल
ORDER_NOT_CANCELLABLEलौटाती है। - @icloud.com इनबॉक्स किराए पर लेने के लिए ऑर्डर बनाते समय
"domain": "icloud.com"भेजें (Gmail के लिए इसे न भेजें; मौजूदा बॉट को बदलाव की ज़रूरत नहीं)। अगर सर्विस iCloud सपोर्ट नहीं करती, या iCloud कुछ देर के लिए बंद है, तोDOMAIN_UNAVAILABLEमिलता है — Gmail पर जाएं और किराया तुरंत हो जाएगा। जीवनचक्र, कैंसल और रिफंड के नियम, और कोड पढ़ने का तरीका Gmail जैसे बिल्कुल वही हैं। - अपने इन्वेंटरी की सर्विस (
provider="inventory", जैसे Cointiply —GET /v1/servicesदेखें) सिर्फ़ iCloud होती हैं; हर ईमेलotp[].codeमें एक लिंक के रूप में आता है, साथ मेंkind,labelऔर पूरा ईमेल टेक्स्टtextमें। ऑर्डर कोrules.windowMinutesमिनट में (windowEndsAtतक) अधिकतमrules.maxCodesईमेल मिलते हैं, उसे कैंसल नहीं किया जा सकता (ORDER_NOT_CANCELLABLE), और समय खत्म होने तक कोई ईमेल न आए तो वह रिफंड के बिना cancelled हो जाता है। उसी इनबॉक्स पर ईमेल पाते रहने के लिए, जब तकcanRerenttrue है,POST /v1/orders/{id}/rerentकॉल करें (कीमत:rerentPriceVnd)। बाकी सभी सेवाओं / ऑर्डर मेंprovider="standard"होता है — 2026-10-24 सेproviderके केवल दो मान हैं:"standard"|"inventory"(असली वेयरहाउसwarehouseमें है); केवल"inventory"से तुलना करें। - Warehouse 2 के ऑर्डर (
warehouse= 2):fee.freeHoursघंटे कोड बिना शुल्क हैं; बिना शुल्क वाली विंडो बंद होने पर नए कोड आना रुक जाता है — नई विंडो खोलने के लिएconfirmFee= true के साथPOST /v1/orders/{id}/next-codeकॉल करें (nextCodeFee.feePriceVndचुकाते हुए),nextCodeFee.hardUntilतक। सामान्य सर्विस के Warehouse 3 ऑर्डर: 24 घंटे कोड बिना शुल्क, कोड आने से पहले कैंसल हो सकते हैं, फिरrerentइस्तेमाल करें। Warehouse 4 के ऑर्डर: ऑर्डर पढ़ने पर नए कोडotp[]में आ जाते हैं,rentExpiresAtतक बिना शुल्क; एक-कोड वाले स्रोत में पहले कोड के बादnextCodeBlockReason="max_codes"हो जाता है। - एक साथ कई ऑर्डर?
POST /v1/orders/statusसे हर कॉल में 100 तक poll करें — एक कॉल में कई ऑर्डर का स्टेटस देखें।
रेट लिमिट
लिमिट हर API key पर लागू होती हैं (किसी अकाउंट की अपनी अलग लिमिट हो सकती है; नहीं तो साइट की डिफ़ॉल्ट लिमिट लागू होती है):
- 100 रिक्वेस्ट/सेकंड — कुछ सेकंड के छोटे बर्स्ट
- 3000 रिक्वेस्ट/मिनट — एक मिनट का कुल ट्रैफ़िक
लिमिट पार करने पर HTTP 429 मिलता है, जिसमें
Retry-After: <seconds> हेडर और body {"success":false,"error":{"code":"RATE_LIMITED",...}} होती है। रिट्राई करने से पहले हेडर में दिए सेकंड तक रुकें। एरर body में वही सेकंड error.retryAfterSec में भी होते हैं (error.retryable = true के साथ)।एरर कोड
हर एरर का आकार एक जैसा है:
{"success":false,"error":{"code":"...","message":"...","retryable":false,"retryAfterSec":null}}2026-10-17 से /v1 के हर एरर में
एरर जवाबों के नमूनेerror.retryable और error.retryAfterSec भी होते हैं (जोड़े गए फ़ील्ड — मौजूदा क्लाइंट में कोई बदलाव ज़रूरी नहीं; details वैसा ही रहता है)। retryable = true ⇒ वही कॉल बाद में सफल हो सकती है: retryAfterSec सेकंड (≥ 1 पूर्णांक) रुककर दोबारा भेजें — स्टॉक खत्म / इनबॉक्स नहीं / warehouse रुका हुआ / प्रोवाइडर एरर ⇒ 5 सेकंड; 429 RATE_LIMITED ⇒ Retry-After हेडर; 409 DUPLICATE_REQUEST जब उसी Idempotency-Key वाला पहला अनुरोध अभी चल रहा हो ⇒ 2 सेकंड। retryable = false (retryAfterSec = null) ⇒ जब तक आप वजह ठीक नहीं करते (बैलेंस, इंतज़ार वाले ऑर्डर की लिमिट, पैरामीटर, API key…), दोबारा कॉल करने से कुछ नहीं होगा। POST /v1/orders का partial.reason भी इन्हीं नियमों पर चलता है। स्टॉक खत्म वाले 409 जवाब (OUT_OF_STOCK, WAREHOUSE_UNAVAILABLE, ALL_WAREHOUSES_EXHAUSTED) पर दोबारा कोशिश करने से पहले पूरे retryAfterSec सेकंड रुकें — इससे पहले कोशिश करने पर आमतौर पर वही जवाब मिलता है — और फिर से किराए पर लेने से पहले GET /v1/services में stock / offers[].stock देखें; पहले से लिए गए ऑर्डर बार-बार पूछने के बजाय webhook से ट्रैक करें।HTTP/1.1 409 Conflict
{
"success": false,
"error": {
"code": "OUT_OF_STOCK",
"message": "This service is currently out of stock",
"retryable": true,
"retryAfterSec": 5
}
}
HTTP/1.1 429 Too Many Requests
Retry-After: 1
{
"success": false,
"error": {
"code": "RATE_LIMITED",
"message": "Rate limit exceeded, retry after 1s",
"retryable": true,
"retryAfterSec": 1
}
}
HTTP/1.1 402 Payment Required
{
"success": false,
"error": {
"code": "INSUFFICIENT_BALANCE",
"message": "Insufficient balance to rent an inbox",
"retryable": false,
"retryAfterSec": null
}
}वेबहुक (पुश सूचनाएँ)
हर खाते के लिए एक URL रजिस्टर करें; जैसे ही किसी ऑर्डर को नया कोड मिलता है (
3 चरणों में सेटअपorder.code) या वह रद्द / रिफ़ंड होता है (order.cancelled), हम उस URL पर एक हस्ताक्षरित JSON इवेंट POST करते हैं। वेबहुक वैकल्पिक हैं और आपके खाते के सभी ऑर्डर पर लागू होते हैं (वेब और API)। डिलीवरी सर्वोत्तम प्रयास पर आधारित है — बैकअप के रूप में धीमी पोलिंग जारी रखें (नीचे देखें)।- अपने URL (और चाहें तो
events) के साथPUT /v1/webhook—data.secret(64 हेक्स अक्षर) सहेजें: हर डिलीवरी की जाँच के लिए इसकी ज़रूरत होती है। PUT दोबारा बुलाने पर वही secret बना रहता है। POST /v1/webhook/test— हम तुरंत एकpingइवेंट भेजते हैं और बताते हैं कि आपके सर्वर ने क्या जवाब दिया (ok,httpStatus,error)।- आपके एंडपॉइंट को 5 सेकंड के भीतर कोई भी 2xx लौटाना चाहिए — पहले जवाब दें, फिर इवेंट प्रोसेस करें। बाकी सब (3xx, 4xx, 5xx, टाइमआउट, कनेक्शन त्रुटि) विफलता माना जाता है और दोबारा भेजा जाता है।
URL
अनुरोध का प्रारूपhttp:// या https:// से शुरू होना चाहिए (मान्य प्रमाणपत्र के साथ) और इंटरनेट से पहुँचने योग्य होना चाहिए: localhost, निजी, link-local, multicast और आरक्षित पते (10.x, 172.16–31.x, 192.168.x, 169.254.x, fc00::/7, fe80::/10…) तथा OTPGmail के अपने सर्वर VALIDATION_ERROR के साथ अस्वीकार किए जाते हैं। हर डिलीवरी से पहले होस्ट नाम फिर से रिज़ॉल्व किया जाता है। रीडायरेक्ट का पालन नहीं किया जाता — अंतिम URL रजिस्टर करें।हर डिलीवरी आपके URL पर JSON बॉडी (UTF-8) और इन हेडर के साथ एक HTTP POST है:
अपने secret को कुंजी बनाकर
रिसीवर के उदाहरण (Python और Node केवल मानक लाइब्रेरी इस्तेमाल करते हैं; curl कमांड आपके अपने रिसीवर पर सही हस्ताक्षर वाली टेस्ट डिलीवरी भेजता है)X-OTPGmail-Timestamp + . + अनुरोध की कच्ची बॉडी पर HMAC-SHA256 को छोटे अक्षरों के hex में निकालें और sha256= के बाद वाले मान से स्थिर-समय तुलना करें। कुंजी स्वयं 64 अक्षरों वाली secret स्ट्रिंग है (उसके UTF-8 बाइट — hex डिकोड न करें)। कच्चे बाइट ही इस्तेमाल करें: JSON को पार्स करके दोबारा सीरियलाइज़ करने से बाइट बदल जाते हैं। आपकी घड़ी से 5 मिनट से ज़्यादा अलग timestamp अस्वीकार करें (रीप्ले से सुरक्षा)।curl
Python
Node.js
# स्थानीय टेस्ट: अपने रिसीवर पर ठीक हमारे जैसे हस्ताक्षर वाली डिलीवरी भेजें
SECRET="9f2c6d1e8b7a4f3c5e0d2b1a6c9e8f7d3b5a1c2e4f6a8b0d9c7e5f3a1b2c4d6e"
TS=$(date +%s)
BODY='{"event":"ping","deliveryId":"6f1d2c3b-8a9e-4f70-b1c2-d3e4f5a6b7c8","sentAt":'$TS'}'
SIG=$(printf '%s.%s' "$TS" "$BODY" | openssl dgst -sha256 -hmac "$SECRET" -hex | sed 's/^.* //')
curl -X POST "http://localhost:8080/" \
-H "Content-Type: application/json" \
-H "X-OTPGmail-Event: ping" \
-H "X-OTPGmail-Delivery: 6f1d2c3b-8a9e-4f70-b1c2-d3e4f5a6b7c8" \
-H "X-OTPGmail-Timestamp: $TS" \
-H "X-OTPGmail-Signature: sha256=$SIG" \
-d "$BODY"{
"event": "order.code",
"deliveryId": "6f1d2c3b-8a9e-4f70-b1c2-d3e4f5a6b7c8",
"sentAt": 1760700125,
"orderId": "k3m9x2p7q1w8e5r4",
"service": "fb",
"warehouse": 1,
"domain": "gmail.com",
"email": "[email protected]",
"code": "482913",
"receivedAt": 1760700124,
"status": "completed",
"otp": [
{
"code": "482913",
"receivedAt": 1760700124
}
]
}उदाहरण बॉडी — order.cancelled{
"event": "order.cancelled",
"deliveryId": "0b7e4c2a-5d1f-4e8b-9a3c-2f6d8e1b4a7c",
"sentAt": 1760701630,
"orderId": "p8v2n5c1x7z3m9k4",
"service": "ig",
"warehouse": 2,
"domain": "gmail.com",
"email": "[email protected]",
"reason": "timeout",
"refundVnd": 1500,
"status": "cancelled"
}उदाहरण बॉडी — ping{
"event": "ping",
"deliveryId": "3c9a1e7f-2b4d-4c6e-8f0a-5d7b9c1e3a2f",
"sentAt": 1760700000
}पुनः प्रयास, विराम और इतिहास- विफल डिलीवरी 10 सेकंड, 1 मिनट, 5 मिनट, 30 मिनट और 2 घंटे बाद दोबारा भेजी जाती है (5 पुनः प्रयास); आख़िरी भी विफल हो तो इवेंट छोड़ दिया जाता है (
failed)। - लगातार 50 विफल प्रयास (सभी इवेंट मिलाकर) वेबहुक को रोक देते हैं:
GET /v1/webhookमेंpausedAtदिखता है, कुछ नहीं भेजा जाता और नए इवेंट कतार में नहीं जुड़ते। - फिर शुरू करने के लिए:
PUT /v1/webhookदोबारा बुलाएँ (वही URL चलेगा) या एक सफलPOST /v1/webhook/testपाएँ — उसके बाद कतार में इंतज़ार कर रहे इवेंट भेजे जाते हैं। GET /v1/webhook/deliveriesअंतिम 100 डिलीवरी उनकी स्थिति, प्रयासों और अंतिम त्रुटि के साथ दिखाता है; इतिहास 7 दिन रखा जाता है।
एक ही इवेंट एक से ज़्यादा बार आ सकता है (जैसे जब आपका 2xx जवाब खो गया हो) और इवेंट क्रम से बाहर आ सकते हैं (कई समानांतर भेजे जाते हैं)। प्रोसेस किए गए
बैकअप के रूप में पोलिंग जारी रखेंdeliveryId सहेजें और दोहराव छोड़ें; किसी ऑर्डर के लिए आने के क्रम के बजाय उसके सबसे नए डेटा (otp, status) पर भरोसा करें।वेबहुक देर से आ सकते हैं (पुनः प्रयास) या छूट सकते हैं (वेबहुक रुका हुआ, आपका सर्वर बंद)। धीमी पोलिंग जारी रखें — जैसे जो ऑर्डर अभी भी
waiting_code में हैं उनके लिए हर 30–60 सेकंड पर GET /v1/orders/{id} — और API से मिले ऑर्डर ऑब्जेक्ट को ही सही स्रोत मानें।PUT/v1/webhook
आपके खाते का वेबहुक रजिस्टर या अपडेट करता है। पहली कॉल इसे बनाती है और नया secret लौटाती है; बाद की कॉल secret वही रखती हैं, वेबहुक को फिर चालू करती हैं और रुका हो तो फिर शुरू करती हैं। events न भेजें तो: नए वेबहुक के लिए दोनों इवेंट, मौजूदा के लिए कोई बदलाव नहीं। URL सार्वजनिक पता होना चाहिए — वरना 400 VALIDATION_ERROR (कारण error.details.problem में)।
पैरामीटर| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
url | string | हाँ | आपका एंडपॉइंट (http:// या https://, सार्वजनिक पता, अधिकतम 2048 अक्षर) |
events | string[] | नहीं | कौन-से इवेंट भेजें: ["order.code", "order.cancelled"] (डिफ़ॉल्ट दोनों) |
curl
Python
Node.js
# data.secret सहेजें — हर डिलीवरी की जाँच के लिए इसकी ज़रूरत है
curl -X PUT "https://otpgmail.net/v1/webhook" \
-H "Authorization: Bearer og_xxx..." \
-H "Content-Type: application/json" \
-d '{"url":"https://your-server.example/otpgmail-webhook","events":["order.code","order.cancelled"]}'{
"success": true,
"data": {
"url": "https://your-server.example/otpgmail-webhook",
"events": [
"order.code",
"order.cancelled"
],
"enabled": true,
"secret": "9f2c6d1e8b7a4f3c5e0d2b1a6c9e8f7d3b5a1c2e4f6a8b0d9c7e5f3a1b2c4d6e",
"pausedAt": null,
"consecutiveFailures": 0,
"createdAt": 1760699000,
"updatedAt": 1760699000
}
}संभावित एरर: UNAUTHORIZED, VALIDATION_ERRORGET/v1/webhook
आपके खाते का वेबहुक, secret, pausedAt और consecutiveFailures सहित। कोई वेबहुक रजिस्टर न हो तो data null होता है।
उदाहरणcurl
Python
Node.js
curl "https://otpgmail.net/v1/webhook" \
-H "Authorization: Bearer og_xxx..."{
"success": true,
"data": {
"url": "https://your-server.example/otpgmail-webhook",
"events": [
"order.code",
"order.cancelled"
],
"enabled": true,
"secret": "9f2c6d1e8b7a4f3c5e0d2b1a6c9e8f7d3b5a1c2e4f6a8b0d9c7e5f3a1b2c4d6e",
"pausedAt": 1760705400,
"consecutiveFailures": 50,
"createdAt": 1760699000,
"updatedAt": 1760705400
}
}संभावित एरर: UNAUTHORIZEDDELETE/v1/webhook
वेबहुक हटाता है; कतार में इंतज़ार कर रहे इवेंट छोड़ दिए जाते हैं। हमेशा 200 — हटाने को कुछ न हो तो data.deleted false होता है।
उदाहरणcurl
Python
Node.js
curl -X DELETE "https://otpgmail.net/v1/webhook" \
-H "Authorization: Bearer og_xxx..."{
"success": true,
"data": {
"deleted": true
}
}संभावित एरर: UNAUTHORIZEDPOST/v1/webhook/test
आपके URL पर अभी एक ping इवेंट भेजता है और नतीजा बताता है: ok (आपके सर्वर ने 2xx लौटाया), httpStatus, durationMs, error। सफल टेस्ट रुके हुए वेबहुक को फिर शुरू कर देता है। प्रति मिनट अधिकतम 10 टेस्ट; पूरे सिस्टम में वेबहुक बंद हों तो 503 MAINTENANCE।
उदाहरणcurl
Python
Node.js
curl -X POST "https://otpgmail.net/v1/webhook/test" \
-H "Authorization: Bearer og_xxx..."{
"success": true,
"data": {
"ok": true,
"httpStatus": 200,
"durationMs": 143,
"error": null,
"deliveryId": "3c9a1e7f-2b4d-4c6e-8f0a-5d7b9c1e3a2f"
}
}आपका सर्वर 2xx न लौटाए तब 200 जवाब
संभावित एरर: {
"success": true,
"data": {
"ok": false,
"httpStatus": 500,
"durationMs": 88,
"error": "HTTP 500",
"deliveryId": "7d2b9f4e-1c6a-4e3b-8d5f-0a9c2e7b1f4d"
}
}UNAUTHORIZED, NOT_FOUND, RATE_LIMITED, MAINTENANCEGET/v1/webhook/deliveries
सबसे नई डिलीवरी, नई पहले (7 दिन रखी जाती हैं): status = queued (अगला प्रयास nextAt पर) | delivered | failed | paused, साथ में attempts, lastHttpStatus और lastError। इवेंट की बॉडी नहीं लौटाई जाती।
पैरामीटर| नाम | टाइप | ज़रूरी | विवरण |
|---|---|---|---|
limit | number | नहीं | डिलीवरी की संख्या, 1–100 (डिफ़ॉल्ट 100) |
curl
Python
Node.js
curl "https://otpgmail.net/v1/webhook/deliveries?limit=20" \
-H "Authorization: Bearer og_xxx..."{
"success": true,
"data": [
{
"id": "0b7e4c2a-5d1f-4e8b-9a3c-2f6d8e1b4a7c",
"event": "order.cancelled",
"orderId": "p8v2n5c1x7z3m9k4",
"status": "queued",
"attempts": 1,
"lastHttpStatus": 503,
"lastError": "HTTP 503",
"nextAt": 1760701640,
"createdAt": 1760701630,
"deliveredAt": null
},
{
"id": "6f1d2c3b-8a9e-4f70-b1c2-d3e4f5a6b7c8",
"event": "order.code",
"orderId": "k3m9x2p7q1w8e5r4",
"status": "delivered",
"attempts": 1,
"lastHttpStatus": 200,
"lastError": null,
"nextAt": null,
"createdAt": 1760700124,
"deliveredAt": 1760700125
}
]
}संभावित एरर: UNAUTHORIZED