विशेष छूट लागू करेंजो कोई भी किसी भी सर्विस के लिए (Facebook, Instagram और Apple को छोड़कर) प्रतिदिन 2000 से अधिक Gmail के लिए OTP किराए पर लेता है और स्पेशल डिस्काउंट चाहता है, वह मुझे मैसेज कर सकता है! पर्याप्त बड़ी मात्रा में अकाउंट रजिस्टर करने वालों के लिए मूल कीमत पर 50% तक की छूट मिल सकती है।
New update 29/09I have just added 4 new warehouses for all services + short-live accounts shop (24h) with email + pass for you to log in, feel free to check them out when you have time

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 "https://otpgmail.net/v1/balance" \
  -H "Authorization: Bearer og_xxx..."
सैंपल रिस्पॉन्स
{
  "success": true,
  "data": {
    "balance": 25000
  }
}
संभावित एरर: UNAUTHORIZED
GET/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 "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
    }
  ]
}
संभावित एरर: UNAUTHORIZED
POST/v1/orders
वेरिफिकेशन कोड पाने वाले इनबॉक्स का ऑर्डर बनाता है — डिफ़ॉल्ट रूप से Gmail, या domain: "icloud.com" भेजने पर iCloud। प्रोवाइडर के इनबॉक्स देते ही आपका बैलेंस कट जाता है। ऑर्डर की लिस्ट लौटाता है (एक, या quantity > 1 होने पर कई)।
आंशिक डिलीवरी: quantity एक अधिकतम सीमा है
  • इनबॉक्स एक-एक करके दिए जाते हैं। अगर प्रोवाइडर के इनबॉक्स बीच में खत्म हो जाएं (जैसे उस समय Warehouse 1 में उस सर्विस के लिए और इनबॉक्स न हों), तो कॉल रुक जाता है और अब तक बने ऑर्डर के साथ HTTP 200 लौटाता है — data quantity से छोटा हो सकता है, और पैसे सिर्फ़ 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 या 503 NO_MAILS_AVAILABLE लौटा सकता है — यह सामान्य है: कॉल के बीच 3–5 सेकंड का अंतर रखते रहें और तभी रुकें जब लगातार कई कॉल फ़ेल हों (जैसे 10 कोशिशें, लगभग एक मिनट); फिर बाद में कोशिश करें, या "warehouse": 99 भेजें ताकि सिस्टम दूसरे Warehouse पर चला जाए। retryable = false (INSUFFICIENT_BALANCE, WAITING_LIMIT_REACHED…) ⇒ पहले वजह ठीक करें (बैलेंस भरें, या खुले ऑर्डर पूरे होने दें)।
  • एरर वाले जवाबों में भी यही दो फ़ील्ड error के अंदर होते हैं: error.retryable और error.retryAfterSec (जैसे 409 OUT_OF_STOCK ⇒ true, 5; 402 INSUFFICIENT_BALANCE ⇒ false, null) — एरर कोड देखें।
Idempotency-Key हेडर (एक UUID) ज़रूरी है। हर नए किराए के लिए नया UUID बनाएं; टाइमआउट के बाद रिट्राई करते समय डुप्लीकेट ऑर्डर से बचने के लिए वही key दोबारा इस्तेमाल करें। यह कॉल प्रोवाइडर के इनबॉक्स देने का इंतज़ार करता है, इसलिए आम तौर पर लगभग 0.3 सेकंड लेता है पर भीड़ के समय (कभी-कभार) 10 सेकंड तक लग सकता है — अपने क्लाइंट का टाइमआउट लगभग 15 सेकंड रखें, 5 सेकंड बाद हार मानकर जल्दी रिट्राई न करें।
पैरामीटर
नामटाइपज़रूरीविवरण
servicestringहाँसर्विस कोड (GET /v1/services से, जैसे "ig", "tg", "fb")
quantitynumberनहींज़्यादा से ज़्यादा कितने इनबॉक्स किराए पर लेने हैं (डिफ़ॉल्ट 1; प्रति रिक्वेस्ट अधिकतम 200) — Warehouse बीच में खत्म हो जाए तो कम मिलते हैं: data[] गिनें और partial पढ़ें
domainstringनहींइनबॉक्स टाइप: "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।
warehousenumberनहींकिस 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 सेक्शन देखें।
उदाहरण
# हर नए ऑर्डर के लिए नई रैंडम 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, MAINTENANCE
GET/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 पर भेजें — वही ऑर्डर ऑब्जेक्ट, रेट लिमिट में एक ही अनुरोध।
पैरामीटर
नामटाइपज़रूरीविवरण
idstringहाँऑर्डर ID (ऑर्डर बनने पर मिला orderId)
उदाहरण
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_FOUND
POST/v1/orders/{id}/cancel
ऑर्डर कैंसल करता है और कीमत का 100% रिफंड करता है। सिर्फ़ तब मुमकिन है जब ऑर्डर waiting_code स्टेटस में हो और कोई कोड न मिला हो।
जिस ऑर्डर को कोड मिल चुका है (एक भी), उसे कैंसल या रिफंड नहीं किया जा सकता — यह वेबसाइट और API दोनों पर लागू है। rules.cancellable = false वाले ऑर्डर (अपने इन्वेंटरी की सर्विस, जैसे Cointiply) कैंसल नहीं हो सकते: इनबॉक्स असाइन होने के बाद कैंसल या रिफंड नहीं होता — cancel कॉल ORDER_NOT_CANCELLABLE लौटाती है। सामान्य सर्विस के Warehouse-3 ऑर्डर (rules.cancellable = true) कोड आने से पहले किसी भी दूसरे ऑर्डर की तरह कैंसल हो सकते हैं।
पैरामीटर
नामटाइपज़रूरीविवरण
idstringहाँकैंसल किए जाने वाले ऑर्डर की ID
उदाहरण
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_ERROR
POST/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 — तीनों में पैसे नहीं कटते।
पैरामीटर
नामटाइपज़रूरीविवरण
idstringहाँइनबॉक्स के पिछले ऑर्डर की ID (जिसमें canRerent = true है)
उदाहरण
# टाइमआउट के बाद रिट्राई करते समय वही 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, MAINTENANCE
POST/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 भेजना ज़रूरी है (न भेजें ⇒ 409 NEXT_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 न भेजें तो कॉल पहले जैसा ही चलता है।
पैरामीटर
नामटाइपज़रूरीविवरण
idstringहाँऑर्डर ID (orderId) — कोई भी warehouse
confirmFeebooleanनहींtrue = आप एक और कोड विंडो खोलने के लिए nextCodeFee.feePriceVnd चुकाने को राज़ी हैं। feePriceVnd = 0 होने पर ज़रूरी नहीं।
refreshbooleanनहींtrue = warehouse 2, ऑर्डर नए कोड का इंतज़ार कर रहा है (listening = true) पर कोड नहीं आ रहा: प्रोवाइडर के पास इनबॉक्स अभी फिर खोलें (इंतज़ार रीफ़्रेश करें) — पुराना इंतज़ार प्रोवाइडर की तरफ़ ईमेल लेना बंद कर चुका हो सकता है। मुफ़्त; हर ऑर्डर पर 5 सेकंड में अधिकतम एक बार। ऑर्डर इंतज़ार में नहीं ⇒ सामान्य कॉल जैसा।
उदाहरण
# बिना शुल्क (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।
पैरामीटर
नामटाइपज़रूरीविवरण
idsstring[]हाँऑर्डर ID (orderId) — हर कॉल में 1 से 100
उदाहरण
# जिन ऑर्डर का आप इंतज़ार कर रहे हैं उनके 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_LIMITED
GET/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 करें।
पैरामीटर
नामटाइपज़रूरीविवरण
statusstringनहींसिर्फ़ यह स्टेटस: waiting_code | completed | cancelled | queued (न भेजें ⇒ सभी)
sincenumberनहींसिर्फ़ वे ऑर्डर जो इस unix समय (सेकंड) पर या उसके बाद बने
limitnumberनहींहर पेज में ऑर्डर: 1–200 (डिफ़ॉल्ट 50)
cursorstringनहींपिछले पेज का nextCursor, बिना बदले
उदाहरण
# रीस्टार्ट के बाद: वे सभी ऑर्डर पेज-दर-पेज इकट्ठा करें जो अभी कोड का इंतज़ार कर रहे हैं
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_LIMITED

Warehouse

हर 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 (जिन सर्विस का स्टॉक अक्सर खत्म होता है उनके लिए सुझाया गया)
"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 मिलता है।
उदाहरण: warehouse = 99 से Facebook Gmail किराए पर लें
# 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}'
offers[] के फ़ील्ड
फ़ील्डटाइपविवरण
warehouse1 | 2 | 3 | 4Warehouse नंबर: 1, 2, 3 या 4।
domainstringऑफ़र का इनबॉक्स टाइप: gmail.com, icloud.com या gmx.com (अतिरिक्त डोमेन — सिर्फ़ कुछ सर्विस, अभी Pokemon)।
pricenumberइस warehouse से एक इनबॉक्स की कीमत (VND)।
stocknumberबचे हुए इनबॉक्स। 0 = स्टॉक खत्म — Warehouse 1 या 2 से किराए पर लेने पर WAREHOUSE_UNAVAILABLE मिलता है; Warehouse 4 फिर भी आज़माया जाता है (उसके स्रोत 0 बताने पर भी अक्सर मेल देते हैं) और कुछ न मिलने पर OUT_OF_STOCK लौटाता है।
maxCodesnumber | nullएक इनबॉक्स पर आ सकने वाले कोड की अधिकतम संख्या; null = कोई सीमा नहीं / पता नहीं (fee देखें)।
rulesobject | nullwarehouse 3 के लिए विंडो के नियम (windowMinutes, maxCodes, cancellable, refundOnTimeout, rerentRatio); warehouse 1, 2 और 4 के लिए null।
feeobject | nullअतिरिक्त कोड की विंडो: किराए से freeHours घंटे बिना शुल्क, फिर हर एक्सटेंशन के लिए किराए की कीमत का paidPct% लगता है, किराए से अधिकतम maxHours घंटे तक (null = कोई सीमा नहीं)। fee = null: कोई शुल्क नहीं — अगर सर्विस एक से ज़्यादा कोड भेजती है तो ऑर्डर की अवधि में अतिरिक्त कोड पर कुछ नहीं लगता (maxCodes तक), जैसा warehouse 1 में।
isDefaultbooleanस्टॉक में उपलब्ध सबसे कम कीमत वाले warehouse के लिए true (बराबरी ⇒ छोटा warehouse नंबर) — warehouse = 0 में यही इस्तेमाल होता है, और 99 में सबसे पहले यही आज़माया जाता है।
Warehouse के हिसाब से नियम
नियमWarehouse 1Warehouse 2Warehouse 3Warehouse 4
पहले कोड का इंतज़ार25 मिनट20 मिनट25 मिनट ¹अधिकतम 25 मिनट (कुछ स्रोतों में कम — असली समय-सीमा ऑर्डर का codeDeadlineAt है)
कोड न आए तोअपने-आप कैंसल, 100% रिफंडअपने-आप कैंसल, 100% रिफंडअपने-आप कैंसल, 100% रिफंड ¹अपने-आप कैंसल, 100% रिफंड
कोड से पहले कैंसलहाँहाँहाँ ¹हाँ
हर इनबॉक्स पर कोडmaxCodes के हिसाब सेकोई सीमा नहींकोई सीमा नहीं ¹maxCodes के हिसाब से (आम तौर पर null = कोई सीमा नहीं; कुछ ऑफ़र के लिए 1)
और कोडअगर सर्विस और कोड भेजे तो 24 घंटे की ऑर्डर अवधि में कोई अतिरिक्त शुल्क नहीं; अपने-आप आते हैं (अलग कॉल की ज़रूरत नहीं)। इनबॉक्स आम तौर पर आखिरी कोड के बाद लगभग 25 मिनट खुला रहता है।fee.freeHours घंटे बिना शुल्क (अभी Gmail 6 घंटे, iCloud 12 घंटे); उसके बाद हर एक्सटेंशन के लिए next-code के ज़रिए कीमत का fee.paidPct% लगता है, अधिकतम fee.maxHours तक (Gmail 24 घंटे, iCloud 10 दिन)24 घंटे तक कोई अतिरिक्त शुल्क नहीं; उसके बाद उसी इनबॉक्स को कीमत के 50% पर फिर किराए पर लें (rerent)warehouse 1 की तरह 24 घंटे की ऑर्डर अवधि में कोई अतिरिक्त शुल्क नहीं — ऑर्डर पढ़ते समय नए कोड दिख जाते हैं; next-code उसे तुरंत दोबारा पढ़ता है।
¹ जो सर्विस सिर्फ़ अपने इन्वेंटरी से बिकती हैं, जैसे Cointiply (provider = "inventory", rules.cancellable = false), वे rules का पालन करती हैं: rules.windowMinutes मिनट में अधिकतम rules.maxCodes ईमेल, कैंसल नहीं, और अगर समय खत्म होने तक कोई ईमेल न आए तो रिफंड नहीं।
nextCodeFee — और कोड का शुल्क (warehouse 2 और 3 के ऑर्डर)
GET /v1/orders/{id} और हर ऑर्डर रिस्पॉन्स में शामिल; warehouse 1 और 4 के ऑर्डर के लिए null (और कोड बिना शुल्क)। Warehouse 2: एक और कोड चाहिए तो POST /v1/orders/{id}/next-code कॉल करें — अगर feePriceVnd 0 से ज़्यादा है तो confirmFee = true भेजना ज़रूरी है। Warehouse 3 (सामान्य सर्विस): बिना शुल्क वाली विंडो खत्म होने पर feePriceVnd उसी इनबॉक्स को दोबारा किराए पर लेने (rerent) की कीमत है।
फ़ील्डटाइपविवरण
feePriceVndnumberअभी next-code कॉल करने पर कटने वाली रकम; 0 = अभी बिना शुल्क वाली विंडो के अंदर।
freeUntilnumber | nullमौजूदा बिना शुल्क वाली विंडो का अंत (unix सेकंड)।
hardUntilnumber | nullअंतिम सीमा (unix सेकंड) — इसके बाद और कोड नहीं आएंगे।
paidPctnumberहर अतिरिक्त विंडो पर लगने वाला शुल्क, किराए की कीमत के % में।
freeHoursnumberएक कोड विंडो के बिना शुल्क वाले घंटे (warehouse 2: Gmail 6, iCloud 12; warehouse 3: 24)।
उदाहरण: warehouse की लिस्ट लें, फिर किसी एक से किराए पर लें
# 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}'
warehouse-2 ऑर्डर का सैंपल (GET /v1/orders/{id})
{
  "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 अक्षर तक)।
लॉट के एक इनबॉक्स के फ़ील्ड (mails[])
फ़ील्डटाइपविवरण
idnumberइनबॉक्स ID — code endpoint का {mailId} पैरामीटर
emailstringईमेल पता
urlstringWarehouse 1: = proxyUrl · warehouse 3: = readUrl (पुरानी स्क्रिप्ट / एक्सपोर्ट फ़ाइलों के लिए रखा गया)
proxyUrlstring | nullWarehouse 1: बिना लॉगिन वाला कोड लिंक · warehouse 3: null
readUrlstringलॉट के कोड पढ़ने का वेब पेज
codeCountnumberमिले कोड की संख्या
lastCodestring | nullसबसे नया कोड (रॉ ईमेल: पहले 300 अक्षर — पूरा टेक्स्ट code endpoint पर है)
lastIsRawbooleantrue = सबसे नया कोड एक रॉ ईमेल है
checkedAtnumber | nullसिस्टम ने इस इनबॉक्स के लिए प्रोवाइडर को आखिरी बार कब जाँचा (unix सेकंड; null = कभी नहीं)
GET/v1/batches
आपके लॉट, सबसे नया पहले (page / pageSize से पेज, 100 तक)। हर लॉट में warehouse (1 = Gmail, 3 = iCloud), status (active | expired | failed), expiresAt, codeCount और readUrl होते हैं।
पैरामीटर
नामटाइपज़रूरीविवरण
pagenumberनहींपेज (डिफ़ॉल्ट 1)
pageSizenumberनहींप्रति पेज लॉट (डिफ़ॉल्ट 20, अधिकतम 100)
उदाहरण
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
  }
}
संभावित एरर: UNAUTHORIZED
GET/v1/batches/{id}
एक लॉट उसके mails[] के साथ — कोड पढ़ने के लिए हर इनबॉक्स की id लें।
Gmail लॉट (warehouse 1): हर इनबॉक्स का proxyUrl आपकी स्क्रिप्ट में ठीक पहले की तरह चलता है। iCloud लॉट (warehouse 3): proxyUrl = null, कोड नीचे वाले endpoint से पढ़ें। एक्सपायर हुए iCloud लॉट में rerentPriceVnd होता है — एक इनबॉक्स को अलग से फिर किराए पर लेने की कीमत (यह वेब पर होता है)।
पैरामीटर
नामटाइपज़रूरीविवरण
idstringहाँलॉट ID (लॉट में किराया पेज और readUrl में दिखती है)
उदाहरण
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_FOUND
GET/v1/batches/{id}/mails/{mailId}/codes
लॉट के एक इनबॉक्स के कोड पढ़ें: अगर इनबॉक्स की बारी हो तो सिस्टम प्रोवाइडर को जाँचता है, फिर मिला हुआ हर कोड लौटाता है, सबसे पुराना पहले — सबसे नया कोड codes[] में आखिरी होता है।
इंतज़ार करते समय हर 5–10 सेकंड में poll करें (इससे ज़्यादा बार कॉल करने पर सिर्फ़ सेव किया हुआ डेटा लौटता है — polledAt नहीं बदलता)। जिन ईमेल से कोड नहीं निकाला जा सका वे isRaw: true के साथ code में जस के तस आते हैं। एक्सपायर हुए लॉट अब भी अपने सेव किए कोड लौटाते हैं पर उन्हें और जाँचा नहीं जाता।
पैरामीटर
नामटाइपज़रूरीविवरण
idstringहाँलॉट ID
mailIdnumberहाँइनबॉक्स ID (mails[].id)
poll0 | 1नहीं0 = सिर्फ़ सेव किए कोड पढ़ें, प्रोवाइडर को न जाँचें (डिफ़ॉल्ट 1)
उदाहरण
# इंतज़ार करते समय हर 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_LIMITED

Buy 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
WarehouseEach account deliversDefault priceStock
1gm_cookieemail · password · cookies · inboxUrl (inbox link) · inboxJsonUrl (emails as JSON) · twoFaUrl (2FA link — just the 6 digits)3,300 VNDA number — published by the source, refreshed every minute. The source checks that accounts are live at purchase time, so you may get fewer — the shortfall is refunded (a partial order; warehouse 99: the rest goes to the next warehouse)
2gm_loginemail · password · loginUrl (quick login link — open it in a desktop browser) · otpUrl (Vinted OTP link — when delivers lists it)6,000 VNDA REFERENCE number from a source sharing the same stock (refreshed every minute; null when it cannot be read) — may be off by a few, never blocks a purchase; a shortfall becomes a partial order with the rest refunded
99As the warehouse that supplied each account (items[].warehouse)Price of the cheapest warehouse on sale (auto.priceVnd)Buys the cheapest warehouse first (auto.order); if it runs out midway the rest goes to the next warehouse at that warehouse's price (the difference is charged — refunded instead if your balance is short); every warehouse out ⇒ MAILSHOP_OUT_OF_STOCK, nothing charged
Warehouse 1 के अकाउंट में लॉगिन (रिकवरी ईमेल नहीं)
  • 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) के साथ आते हैं — लॉगिन के लिए इसे कंप्यूटर के ब्राउज़र में खोलें।
3 steps
  1. 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, call GET /v1/mail-shop/quote.
  2. Buy: POST /v1/mail-shop/orders with {"warehouse": 1 | 2 | 99, "quantity": N} + header Idempotency-Key (a new UUID per purchase). The response is the order, usually already completed with items[].
  3. Get the accounts: read items[] (table below) or download the TXT GET /v1/mail-shop/orders/{id}/download. status = pending ⇒ poll GET /v1/mail-shop/orders/{id} every 5 seconds until completed / partial / failed.
# 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..."
Fields of an account (items[])
फ़ील्डटाइपविवरण
lineNonumberPosition in the order (1, 2, …) — the {lineNo} of the inbox endpoints
warehouse1 | 2Warehouse that supplied this account
emailstringGmail address
passwordstringPassword
recoverystring?Recovery email — only when the source provides one; warehouse 1 (gm_cookie) accounts have NONE (sign in with the cookies, see the sign-in notes above)
cookiesstring | nullWarehouse 1: login cookies (JSON)
inboxUrlstring | nullWarehouse 1: inbox page without an API key (https://otpgmail.net/mail/{code}); null = link turned off
inboxJsonUrlstring | nullWarehouse 1: the same link + ?json ⇒ emails as JSON (section below)
twoFaUrlstring | nullWarehouse 1: the 2FA LINK (https://otpgmail.net/2fa/{code} — same code + expiry as inboxUrl): GET / open it in a browser ⇒ JUST the 6-digit 2FA code (section below). null = link turned off. The .txt file has this column when downloaded with ?twofa=1
inboxLinkExpiresAtnumber | nullWarehouse 1: when the link expires (unix seconds); null = no limit
loginUrlstring | nullWarehouse 2: quick login link
otpUrlstring | nullWarehouse 2: the account's Vinted OTP link — open it in a browser to see the code, ?json ⇒ JSON (section below). null = this account has no link
otpService"vinted" | nullWarehouse 2: the service of otpUrl
rawLinestringThe whole account on one line (cookies compacted) — copy it as is
Read the inbox as JSON (inboxJsonUrl)
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"
# 424819
Order statuses
स्टेटसविवरण
pendingBeing delivered — accounts that arrived are in items[]; poll again in 5 seconds
completedFully delivered. Final.
partialDelivered short — the shortfall was refunded (refundVnd; message = the reason + the source's own words when it gave any). Final.
failedNothing delivered — fully refunded (message as above). Final.
refundedRefunded by an admin (refundVnd). Final.
Rules
  • Money: chargedVnd = Σ route[].quantity × unitPriceVnd (a 99 order split across warehouses ⇒ two legs in route). Shortfalls are refunded automatically (refundVnd). Delivered accounts are not refunded — the only warranty is the warehouse's terms (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 ⇒ 429 RATE_LIMITED.
  • Common errors: MAILSHOP_OUT_OF_STOCK 409 (details.stock = how many you can buy now) · MAILSHOP_QTY_LIMIT 400 (details.max) · INSUFFICIENT_BALANCE 402 · MAILSHOP_DISABLED 503 (warehouse / section paused) · MAILSHOP_SUPPLIER_ERROR 502 (the source refused at once — a failed order was recorded and refunded, details.orderId) · VALIDATION_ERROR 400 (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 "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
      ]
    }
  }
}
संभावित एरर: UNAUTHORIZED
GET/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.
पैरामीटर
नामटाइपज़रूरीविवरण
warehouse1 | 2 | 99नहींMail-shop warehouse: 1 = email + password + cookies + inbox link · 2 = email + password + login link · 99 = automatic, cheapest first. Send warehouse OR product
productstringनहींInstead of warehouse: gm_cookie (= warehouse 1) | gm_login (= warehouse 2)
quantitynumberनहींNumber of accounts (default 1)
उदाहरण
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_FOUND
POST/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.
पैरामीटर
नामटाइपज़रूरीविवरण
warehouse1 | 2 | 99नहींMail-shop warehouse: 1 = email + password + cookies + inbox link · 2 = email + password + login link · 99 = automatic, cheapest first. Send warehouse OR product
productstringनहींInstead of warehouse: gm_cookie (= warehouse 1) | gm_login (= warehouse 2)
quantitynumberनहींNumber of accounts (default 1)
Idempotency-KeystringहाँHeader: a new UUID for every new purchase — reuse it only to retry that same purchase
उदाहरण
# 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, MAINTENANCE
GET/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).
पैरामीटर
नामटाइपज़रूरीविवरण
pagenumberनहींPage (default 1)
pageSizenumberनहींOrders per page (default 20, max 100)
उदाहरण
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
  }
}
संभावित एरर: UNAUTHORIZED
GET/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.
पैरामीटर
नामटाइपज़रूरीविवरण
idstringहाँOrder ID (data.id returned by the purchase)
उदाहरण
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_FOUND
GET/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.
पैरामीटर
नामटाइपज़रूरीविवरण
idstringहाँOrder ID (data.id returned by the purchase)
उदाहरण
curl "https://otpgmail.net/v1/mail-shop/orders/ORDER_ID/download" \
  -H "Authorization: Bearer og_xxx..." \
  -o mail-ORDER_ID.txt
सैंपल रिस्पॉन्स
email|password|cookies|inboxUrl
[email protected]|Pw7Xq!k3d|[{"domain":".google.com","name":"SID","value":"g.a000…"}]|https://otpgmail.net/mail/Q7xK2mP9vL4tR8wN3cB6yH1d
संभावित एरर: UNAUTHORIZED, NOT_FOUND, VALIDATION_ERROR
GET/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.
पैरामीटर
नामटाइपज़रूरीविवरण
idstringहाँOrder ID (data.id returned by the purchase)
lineNonumberहाँAccount number within the order (items[].lineNo)
maxnumberनहींNumber of latest emails: 10 (default), 20, 50, 100 or 200
उदाहरण
# 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_ERROR
GET/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.
पैरामीटर
नामटाइपज़रूरीविवरण
idstringहाँOrder ID (data.id returned by the purchase)
lineNonumberहाँAccount number within the order (items[].lineNo)
उदाहरण
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_ERROR
GET/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).
पैरामीटर
नामटाइपज़रूरीविवरण
idstringहाँOrder ID (data.id returned by the purchase)
lineNonumberहाँAccount number within the order (items[].lineNo)
उदाहरण
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

ऑर्डर का जीवनचक्र

स्टेटसविवरण
कोड का इंतज़ारनया बना ऑर्डर, पहले कोड का इंतज़ार। GET /v1/orders/{id} को हर 3–5 सेकंड में poll करें।
पूरा हुआपहला कोड आ गया — स्टेटस तुरंत बदल जाता है। अगर सर्विस एक से ज़्यादा कोड भेजती है तो और कोड फिर भी आ सकते हैं (ऑर्डर की अवधि में कोई अतिरिक्त शुल्क नहीं; सीमा और विंडो हर warehouse के हिसाब से); poll करते रहें, हर नया कोड otp[] के अंत में दिखता है।
कैंसल हुआ100% वापसी। ऐसा तब होता है जब आप /cancel कॉल करते हैं (कोड आने से पहले), या codeDeadlineAt (अधिकतम 25 मिनट) तक कोई कोड नहीं आता।
ज़रूरी बातें:
  • जब तक ऑर्डर 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 हो जाता है। उसी इनबॉक्स पर ईमेल पाते रहने के लिए, जब तक canRerent true है, 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
  }
}
एरर कोडHTTPretryable · retryAfterSecमतलब
UNAUTHORIZED401false · nullAPI key गलत है या नहीं भेजी गई।
ACCOUNT_LOCKED403false · nullअकाउंट लॉक है — उसकी key से किया गया हर अनुरोध ठुकरा दिया जाता है। सपोर्ट से संपर्क करें।
FORBIDDEN403false · nullकिराए की प्रक्रिया के दौरान अकाउंट सक्रिय नहीं रहा (अभी-अभी लॉक हुआ है)।
NOT_FOUND404false · nullआपके अकाउंट में इस ID का कोई ऑर्डर / लॉट / इनबॉक्स नहीं है (दूसरे अकाउंट के ऑर्डर पर भी 404 आता है)।
VALIDATION_ERROR400false · nullरिक्वेस्ट के पैरामीटर सही नहीं हैं (गलत टाइप, ज़रूरी फ़ील्ड गायब, आदि)।
INSUFFICIENT_BALANCE402false · nullऑर्डर का पेमेंट करने के लिए अकाउंट का बैलेंस कम है।
SERVICE_DISABLED409false · nullसर्विस कोड मौजूद नहीं है या सर्विस अस्थायी रूप से बंद है। सही कोड GET /v1/services से लें।
OUT_OF_STOCK409true · 5रिक्वेस्ट के समय सर्विस में (चुने गए इनबॉक्स टाइप के लिए) कोई इनबॉक्स उपलब्ध नहीं है।
DOMAIN_UNAVAILABLE409false · nullसर्विस चुना गया इनबॉक्स टाइप नहीं देती — iCloud अभी सपोर्टेड नहीं है / कुछ देर के लिए बंद है, या सर्विस में gmx.com इनबॉक्स नहीं हैं। Gmail किराए पर लेने के लिए domain "gmail.com" भेजें (या फ़ील्ड न भेजें)।
WAREHOUSE_UNAVAILABLE409true · 5 / falseचुना गया warehouse यह सर्विस/इनबॉक्स टाइप नहीं बेचता, रुका हुआ है या अभी खत्म हुआ है। offers[] से कोई दूसरा warehouse चुनें, या warehouse = 99 भेजकर सिस्टम को स्टॉक वाला चुनने दें। अगर वह warehouse (या इस सर्विस को बेचने वाले सभी warehouse) आपके खाते के लिए उपलब्ध नहीं है, तो retryable = false — दोबारा कॉल करने से फायदा नहीं, कोई दूसरा warehouse इस्तेमाल करें।
ALL_WAREHOUSES_EXHAUSTED409true · 5सिर्फ़ warehouse = 99 के साथ: स्टॉक वाले हर warehouse को (सबसे कम कीमत से शुरू करके) आज़माया गया और सब स्टॉक से बाहर या फेल थे — या हर warehouse का स्टॉक शून्य बताता है। कुछ नहीं कटा; बाद में फिर कोशिश करें।
NO_MAILS_AVAILABLE503true · 5प्रोवाइडर के पास इस सर्विस के लिए कोई इनबॉक्स नहीं बचा (कुछ देर के लिए खत्म)।
QUANTITY_EXCEEDED400false · nullquantity प्रति रिक्वेस्ट की अधिकतम सीमा (अभी 200) से ज़्यादा है।
WAITING_LIMIT_REACHED429false · nullएक साथ बहुत सारे ऑर्डर कोड का इंतज़ार कर रहे हैं (आपके अकाउंट की एक साथ waiting_code ऑर्डर की सीमा पार हो गई) — कुछ पूरे होने दें, फिर दोबारा किराए पर लें।
ORDER_NOT_CANCELLABLE409false · nullऑर्डर कैंसल नहीं हो सकता — हो सकता है उसे कोड मिल चुका हो, या वह अब waiting_code स्टेटस में न हो। अगर ऑर्डर में अभी पहला कोड नहीं आया है तो next-code भी यही कोड लौटाता है।
RERENT_NOT_AVAILABLE409false · nullऑर्डर दोबारा किराए पर नहीं लिया जा सकता। Warehouse 3: यह इनबॉक्स का सबसे नया ऑर्डर नहीं है, इनबॉक्स अब आपके अकाउंट से जुड़ा नहीं है, या पिछली रिसीविंग विंडो अभी खुली है। Warehouse 2: ऑर्डर अभी बंद नहीं हुआ है (अब भी कोड पा सकता है — next-code इस्तेमाल करें), दोबारा किराए के लिए बहुत पुराना है, ईमेल पर कोई दूसरा चालू ऑर्डर है, या सर्विस रुकी हुई है। Warehouse 1 और 4 में दोबारा किराया नहीं है।
RERENT_EMAIL_BANNED409false · nullWarehouse 2 में दोबारा किराया: प्रोवाइडर बताता है कि ईमेल को सर्विस ने लॉक कर दिया है (email banned) — दोबारा किराए पर नहीं लिया जा सकता; पैसे नहीं कटते।
RERENT_MAIL_GONE409false · nullWarehouse 2 में दोबारा किराया: प्रोवाइडर अब यह ईमेल फिर से नहीं खोल सकता — नया किराए पर लें; पैसे नहीं कटते।
NEXT_CODE_FEE_CONFIRM409false · nullwarehouse-2 ऑर्डर की बिना शुल्क वाली विंडो खत्म हो चुकी है — शुल्क (nextCodeFee.feePriceVnd) चुकाने के लिए next-code को confirmFee: true के साथ फिर कॉल करें। कुछ नहीं कटा है।
EMAIL_BANNED409false · nullईमेल को सर्विस ने लॉक कर दिया है (प्रोवाइडर email banned बताता है) — वह और कोड नहीं पा सकता; नया किराए पर लें। 2026-10-02 से (पहले ORDER_EXPIRED, वही HTTP 409)।
ORDER_EXPIRED409false · nullऑर्डर में अब और कोड नहीं आ सकते — उसका समय खत्म हो गया (rentExpiresAt / nextCodeFee.hardUntil), प्रोवाइडर ने इनबॉक्स बंद कर दिया, कोड की सीमा (maxCodes) पूरी हो गई, या सर्विस में "अगला कोड" नहीं है। वजह order.nextCodeBlockReason में है।
RATE_LIMITED429true · = Retry-Afterआपकी API key पर 100 रिक्वेस्ट/सेकंड या 3000 रिक्वेस्ट/मिनट से ज़्यादा (किसी अकाउंट की अपनी अलग लिमिट हो सकती है)। Retry-After हेडर बताता है कि कितने सेकंड रुकना है। warehouse 2 में POST /v1/orders और /rerent यह कोड तब भी लौटाते हैं जब अकाउंट ने पिछले 60 मिनट में warehouse 2 के बहुत सारे ऑर्डर बिना कोड के कैंसल किए हों और बहुत कम ऑर्डर पर कोड आया हो — कैंसल की दर घटने तक warehouse 2 से किराए पर लेना रुका रहता है ("warehouse": 99 भी इस एरर के साथ वहीं रुक जाता है — तब तक कोई दूसरा warehouse चुनें)। Facebook / Instagram (fb, fbb, ig) को इससे छूट है।
DUPLICATE_REQUEST409true · 2 / falseयह Idempotency-Key किसी दूसरे payload या endpoint के साथ पहले ही इस्तेमाल हो चुकी है, या इस key वाला पहला अनुरोध अभी चल रहा है (थोड़ी देर बाद फिर कोशिश करें)। दूसरा ऑर्डर बनाने के लिए नई key बनाएँ।
PROVIDER_ERROR502true · 5इनबॉक्स प्रोवाइडर की तरफ़ से एरर (कुछ देर के लिए — कुछ सेकंड बाद रिट्राई करें)।
MAINTENANCE503false · nullसिस्टम मेंटेनेंस में है — ऑर्डर बनाना और कैंसल करना रुका हुआ है।
MAILSHOP_DISABLED503false · nullकम समय चलने वाला Gmail खरीदना अभी रुका हुआ है, या यह प्रोडक्ट बंद है — बाद में फिर कोशिश करें।
MAILSHOP_PRODUCT_NOT_FOUND404false · nullइस कोड का कोई प्रोडक्ट नहीं है — सही code यहाँ से लें: GET /v1/mail-shop/products.
MAILSHOP_OUT_OF_STOCK409false · nullमौजूदा कीमत पर इस मात्रा के लिए स्टॉक काफ़ी नहीं है — error.details.stock = अभी कितने अकाउंट खरीदे जा सकते हैं।
MAILSHOP_QTY_LIMIT400false · nullquantity प्रति ऑर्डर की अधिकतम सीमा (अभी 500) से ज़्यादा है — error.details.max देखें।
MAILSHOP_SUPPLIER_ERROR502false · nullसोर्स ने खरीद तुरंत ठुकरा दी: एक failed ऑर्डर दर्ज हुआ और पैसा रिफंड हो गया (error.details.orderId)। बाद में नई Idempotency-Key के साथ फिर कोशिश करें।
INTERNAL500false · nullअनपेक्षित सर्वर एरर — बाद में फिर कोशिश करें; बार-बार हो तो सपोर्ट से संपर्क करें।

वेबहुक (पुश सूचनाएँ)

हर खाते के लिए एक URL रजिस्टर करें; जैसे ही किसी ऑर्डर को नया कोड मिलता है (order.code) या वह रद्द / रिफ़ंड होता है (order.cancelled), हम उस URL पर एक हस्ताक्षरित JSON इवेंट POST करते हैं। वेबहुक वैकल्पिक हैं और आपके खाते के सभी ऑर्डर पर लागू होते हैं (वेब और API)। डिलीवरी सर्वोत्तम प्रयास पर आधारित है — बैकअप के रूप में धीमी पोलिंग जारी रखें (नीचे देखें)।
3 चरणों में सेटअप
  1. अपने URL (और चाहें तो events) के साथ PUT /v1/webhook — data.secret (64 हेक्स अक्षर) सहेजें: हर डिलीवरी की जाँच के लिए इसकी ज़रूरत होती है। PUT दोबारा बुलाने पर वही secret बना रहता है।
  2. POST /v1/webhook/test — हम तुरंत एक ping इवेंट भेजते हैं और बताते हैं कि आपके सर्वर ने क्या जवाब दिया (ok, httpStatus, error)।
  3. आपके एंडपॉइंट को 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 है:
हेडरमान
Content-Typeapplication/json
User-AgentOTPGmail-Webhook/1
X-OTPGmail-Eventइवेंट का नाम: order.code, order.cancelled या ping
X-OTPGmail-Deliveryइवेंट की अद्वितीय ID (UUID) — बॉडी के deliveryId के बराबर और हर पुनः प्रयास में अपरिवर्तित
X-OTPGmail-Timestampइस प्रयास पर हस्ताक्षर का Unix समय (सेकंड) — बॉडी के sentAt के बराबर
X-OTPGmail-Signaturesha256= + आपके secret को कुंजी बनाकर timestamp + "." + कच्ची बॉडी पर HMAC-SHA256 का छोटे अक्षरों वाला hex
हस्ताक्षर जाँचें
अपने secret को कुंजी बनाकर X-OTPGmail-Timestamp + . + अनुरोध की कच्ची बॉडी पर HMAC-SHA256 को छोटे अक्षरों के hex में निकालें और sha256= के बाद वाले मान से स्थिर-समय तुलना करें। कुंजी स्वयं 64 अक्षरों वाली secret स्ट्रिंग है (उसके UTF-8 बाइट — hex डिकोड न करें)। कच्चे बाइट ही इस्तेमाल करें: JSON को पार्स करके दोबारा सीरियलाइज़ करने से बाइट बदल जाते हैं। आपकी घड़ी से 5 मिनट से ज़्यादा अलग timestamp अस्वीकार करें (रीप्ले से सुरक्षा)।
रिसीवर के उदाहरण (Python और Node केवल मानक लाइब्रेरी इस्तेमाल करते हैं; curl कमांड आपके अपने रिसीवर पर सही हस्ताक्षर वाली टेस्ट डिलीवरी भेजता है)
# स्थानीय टेस्ट: अपने रिसीवर पर ठीक हमारे जैसे हस्ताक्षर वाली डिलीवरी भेजें
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"
इवेंट
इवेंटकब भेजा जाता है
order.codeऑर्डर को नया कोड मिला — हर कोड पर एक इवेंट, उसी इनबॉक्स पर आने वाले अगले कोड भी शामिल। code नया कोड है; otp उस समय तक ऑर्डर के सभी कोड पुराने से नए क्रम में देता है (GET /v1/orders/{id} जैसा; बॉडी 64 KB से बड़ी होने पर केवल नया कोड)।
order.cancelledऑर्डर रद्द या रिफ़ंड हुआ — हर ऑर्डर पर एक बार: समय-सीमा से पहले कोई कोड नहीं आया (timeout), आपने रद्द किया (user), किसी व्यवस्थापक ने रद्द किया (admin), या वेयरहाउस विफल होने पर रिफ़ंड हुआ (provider)। refundVnd = आपके बैलेंस में लौटाए गए VND (सेवा के नियम रिफ़ंड न देते हों तो 0)।
pingकेवल POST /v1/webhook/test से।
इवेंट के फ़ील्ड
फ़ील्डटाइपविवरण
eventstringइवेंट का नाम (X-OTPGmail-Event हेडर में भी)
deliveryIdstringइवेंट की अद्वितीय ID (UUID, = X-OTPGmail-Delivery) — डुप्लिकेट छोड़ने के लिए सहेजें
sentAtnumberइस प्रयास का Unix समय (= X-OTPGmail-Timestamp)
orderIdstringऑर्डर ID — GET /v1/orders/{id} वाली ही
servicestringसेवा कोड
warehouse1 | 2 | 3 | 4 | nullइनबॉक्स देने वाला वेयरहाउस 1–4; ऑर्डर को कभी इनबॉक्स न मिला हो तो null
domainstringइनबॉक्स का डोमेन: gmail.com, icloud.com या gmx.com
emailstring | nullकिराए पर लिए गए इनबॉक्स का पता
codestringकेवल order.code: नया कोड — यह लिंक या पूरा ईमेल भी हो सकता है, otp[].code की तरह
receivedAtnumberकेवल order.code: कोड आने का Unix समय
statusstringउस समय ऑर्डर की स्थिति: order.code के लिए completed, order.cancelled के लिए cancelled (जिस ऑर्डर में पहले से कोड हों, उसे व्यवस्थापक रिफ़ंड करे तो वह completed ही रहता है)
otparrayकेवल order.code: उस समय तक के सभी कोड, [{code, receivedAt}], पुराने से नए
reasonstringकेवल order.cancelled: timeout | user | admin | provider
refundVndnumberकेवल order.cancelled: आपके बैलेंस में रिफ़ंड हुए VND (0 = कोई रिफ़ंड नहीं)
उदाहरण बॉडी — order.code
{
  "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 में)।
पैरामीटर
नामटाइपज़रूरीविवरण
urlstringहाँआपका एंडपॉइंट (http:// या https://, सार्वजनिक पता, अधिकतम 2048 अक्षर)
eventsstring[]नहींकौन-से इवेंट भेजें: ["order.code", "order.cancelled"] (डिफ़ॉल्ट दोनों)
उदाहरण
# 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_ERROR
GET/v1/webhook
आपके खाते का वेबहुक, secret, pausedAt और consecutiveFailures सहित। कोई वेबहुक रजिस्टर न हो तो data null होता है।
उदाहरण
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
  }
}
संभावित एरर: UNAUTHORIZED
DELETE/v1/webhook
वेबहुक हटाता है; कतार में इंतज़ार कर रहे इवेंट छोड़ दिए जाते हैं। हमेशा 200 — हटाने को कुछ न हो तो data.deleted false होता है।
उदाहरण
curl -X DELETE "https://otpgmail.net/v1/webhook" \
  -H "Authorization: Bearer og_xxx..."
सैंपल रिस्पॉन्स
{
  "success": true,
  "data": {
    "deleted": true
  }
}
संभावित एरर: UNAUTHORIZED
POST/v1/webhook/test
आपके URL पर अभी एक ping इवेंट भेजता है और नतीजा बताता है: ok (आपके सर्वर ने 2xx लौटाया), httpStatus, durationMs, error। सफल टेस्ट रुके हुए वेबहुक को फिर शुरू कर देता है। प्रति मिनट अधिकतम 10 टेस्ट; पूरे सिस्टम में वेबहुक बंद हों तो 503 MAINTENANCE।
उदाहरण
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, MAINTENANCE
GET/v1/webhook/deliveries
सबसे नई डिलीवरी, नई पहले (7 दिन रखी जाती हैं): status = queued (अगला प्रयास nextAt पर) | delivered | failed | paused, साथ में attempts, lastHttpStatus और lastError। इवेंट की बॉडी नहीं लौटाई जाती।
पैरामीटर
नामटाइपज़रूरीविवरण
limitnumberनहींडिलीवरी की संख्या, 1–100 (डिफ़ॉल्ट 100)
उदाहरण
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