StampMitraDevelopers

गाइड

बैलेंस, इस्तेमाल और rate limit: API से अपना खाता पढ़ना

अपने wallet का बैलेंस, उसकी हालत और बची हुई calls की संख्या एक छोटे endpoint से पढ़ें, और भारतीय समय के हिसाब से महीने का इस्तेमाल दूसरे endpoint से। authenticated calls के साथ rate limit header आते हैं, 429 पर रुकने का समय बताने वाला header भी, और लाइव key को wallet की हालत का संकेत मिलता है, सही रकम कभी नहीं।

लेखक: StampMitra Developer Teamअंतिम अपडेट: यह पेज English में पढ़ें

रात के दो बजे आपके signup flow में अचानक errors आने लगें और सुबह पता चले कि वजह सिर्फ इतनी थी कि वॉलेट खाली हो गया था, तो यह कहानी बहुत से teams की है। अब StampMitra में यह जानने के लिए dashboard खोलने की जरूरत नहीं है। GET /v1/account/balance से बैलेंस और उसकी हालत मिलती है, GET /v1/account/usage से इस महीने और पिछले महीने का इस्तेमाल मिलता है, और आपकी रोजमर्रा की verification calls के response headers बताते हैं कि rate limit में कितनी जगह बची है।

यह लेख उस developer के लिए है जो integration संभालता है, उसके लिए नहीं जो रिचार्ज करता है। यहाँ हर field का मतलब, requests गिनने का तरीका, किस route पर कौन सा header आता है और ऐसा तरीका मिलेगा जिसे आप अपने सिस्टम में सीधे लगा सकते हैं, ताकि बैलेंस खत्म होने से आपके end user को कभी अटकना न पड़े।

अगर आपने अभी पहली call नहीं की है, तो पहले quickstart और authentication docs देख लें। errors के हिस्से के लिए API errors और उनका handling साथ में पढ़ना काम आएगा।

मुख्य बातें

  • GET /v1/account/balance आपको रुपये और पैसे दोनों में बैलेंस, low-balance की सीमा, हालत (OK, LOW_BALANCE, FINISHED) और अंदाजा देता है कि बैलेंस से कितनी calls हो सकती हैं।
  • GET /v1/account/usage चालू और पिछले महीने का हिसाब देता है: requests, billed requests, वे failed calls जिनका बिल नहीं बना, GST से पहले का खर्च, product-वार और दिन-वार आँकड़े। दिन और महीने भारतीय समय (IST) के हिसाब से कटते हैं।
  • जिस key के पास कोई भी verification scope है, वह अपने ही organisation का हिसाब पढ़ सकती है। कोई नया scope नहीं जुड़ा, और कोई key दूसरे organisation का डेटा कभी नहीं देख सकती।
  • live key को authenticated calls पर X-Wallet-State मिलता है, और X-Wallet-Balance-Low: true सिर्फ तब आता है जब बैलेंस कम हो। सही रकम header में कभी नहीं जाती, क्योंकि headers proxy और load balancer के logs में छप जाते हैं।
  • rate limit वाले routes पर X-RateLimit-Limit, X-RateLimit-Remaining और X-RateLimit-Reset आते हैं, और 429 पर Retry-After। इनसे आप दीवार से टकराने से पहले ही रफ्तार घटा सकते हैं।
  • ये headers वैकल्पिक हैं। इन्हें operationally बंद भी किया जा सकता है और कुछ routes पर ये आते ही नहीं, इसलिए अपना client ऐसा लिखें कि इनके बिना भी चले।
  • sandbox key को सिर्फ rate limit वाले headers मिलते हैं। उसके balance endpoint का जवाब sandbox की सूचना और शून्य रकम होती है, असली बैलेंस नहीं।
  • balance endpoint को इंसानी रफ्तार से poll करें, यानी मिनट में एक बार काफी है। दोनों endpoints कुछ सेकंड cache होते हैं और हर key पर मिनट में साठ requests तक सीमित हैं।

पहले समझें कि बैलेंस पर नजर क्यों रखनी है

per-call billing वाली API में एक ही failure ऐसा है जिसका पहले से अंदाजा लगाया जा सकता है: बैलेंस का शून्य हो जाना। तब live calls 402 के साथ रुक जाती हैं, और सबसे पहले असर उस ग्राहक पर पड़ता है जो उस वक्त signup के बीच में था। इसका इलाज code में नहीं है। रिचार्ज किसी इंसान को करना है। code इतना कर सकता है कि वह इंसान कई दिन पहले खबर पाए, और अगर फिर भी न कर पाए तो flow शालीनता से धीमा हो।

पहले बैलेंस देखने के रास्ते सिर्फ dashboard और invoice वाले emails थे। जो founder हर सुबह खुद देखता है उसके लिए यह ठीक है, लेकिन जिस कंपनी में on-call रोटा है उसके लिए कमजोर। जो बैलेंस API से पढ़ा जा सकता है, वह metric बन सकता है, Slack alert बन सकता है, आपके अपने admin panel का banner बन सकता है, या ऐसा flag जो गैर-जरूरी काम रोक दे।

इस्तेमाल का हिसाब दूसरी वजह से जरूरी है। finance को product-वार और दिन-वार खर्च चाहिए, support को जानना है कि किसी घंटे में failures क्यों दिखे, और engineering को देखना है कि traffic plan की सीमा से तेज बढ़ रहा है या नहीं। usage endpoint तीनों सवालों का जवाब एक response में देता है, वह भी भारतीय कैलेंडर के दिनों में, ताकि आँकड़े आपके accountant की सोच से मेल खाएं।

तीसरा टुकड़ा rate limit है। जो सीमा सिर्फ 429 से पता चले, वह production में जाकर पता चलने वाली सीमा है। headers की मदद से समझदार client बची हुई जगह देखकर खुद अपनी रफ्तार तय कर सकता है, जो retry करने से सस्ता पड़ता है।

इस लेख में क्या शामिल नहीं है

रिचार्ज करना, invoices और dashboard इस पन्ने से बाहर हैं। top-up की जानकारी pricing पेज और wallet docs में है, और order events के webhooks webhooks पेज पर हैं। यहाँ बात सिर्फ स्थिति को पढ़ने की है, उसे बदलने की नहीं।

क्या नया है और क्या जैसा था वैसा ही है

यहाँ बताई हर चीज सिर्फ जोड़ी गई है। किसी मौजूदा endpoint, body के field, status code, error code या header में बदलाव नहीं हुआ। पिछले महीने लिखा आपका client बिना एक byte बदले वैसे ही चलता रहेगा।

दो नए read-only endpoints हैं: GET /v1/account/balance और GET /v1/account/usage। authenticated calls पर कुछ नए response headers हैं: तीन X-RateLimit-*, जिस 429 पर Retry-After नहीं था उस पर Retry-After, X-Wallet-State और X-Wallet-Balance-Low। बस इतना ही।

इससे दो बातें निकलती हैं। पहली, काम चलाते रहने के लिए आपको कुछ बदलना नहीं है। दूसरी, नई जानकारी चाहिए तो उसे पढ़ने वाला code आप जोड़ेंगे, और उस code को हर नई value को वैकल्पिक मानना चाहिए। verification calls की body headers के साथ और बिना, दोनों हालत में बिल्कुल एक जैसी है, इसलिए सख्त JSON parser पर कोई असर नहीं पड़ता।

मिलते-जुलते मौजूदा endpoints अपना व्यवहार नहीं बदलते। GET /v1/usage/summary अब भी billing period के कुल आँकड़े और service-वार calls देता है। GET /v1/api-credit-wallet अब भी wallet का record देता है। नए endpoints इनके बगल में हैं और अलग सवालों के जवाब देते हैं: कच्ची गिनती की जगह खर्च और हालत।

Versioning

प्रकाशित OpenAPI document 1.0.0 से 1.1.0 पर गया, यानी minor बदलाव, क्योंकि यह पीछे की तरफ संगत जोड़ है। generated clients को दो नए operations मिलते हैं: getAccountBalance और getAccountUsage। document /openapi.json से लें या Postman collection import करें, जिसमें दोनों requests मौजूद हैं।

कौन पढ़ सकता है: key, scope और organisations की दीवार

दोनों endpoints में authentication बाकी हर /v1 route जैसा ही है। Authorization: Bearer sk_live_... भेजें या x-api-key header, ठीक वैसे जैसे authentication docs में लिखा है।

scope का नियम जानबूझकर हल्का रखा गया है। जिस key के पास verification. से शुरू होने वाला कोई भी scope है, वह अपने organisation का बैलेंस और usage पढ़ सकती है। e-Stamp scope वाली key भी पढ़ सकती है, क्योंकि e-Stamp calls का भुगतान उसी wallet से होता है। जिस key के पास सिर्फ असंबंधित scopes हैं, जैसे orders.read या payments.read, उसे INSUFFICIENT_SCOPE code के साथ 403 मिलता है। key न हो या गलत हो तो हर जगह की तरह 401।

दो organisations के बीच दीवार

organisation और environment हमेशा key से तय होते हैं, request से नहीं। आप ?organizationId=... जोड़ दें या किसी और organisation का नाम लिखकर header भेज दें, तो उसे अनदेखा कर दिया जाता है। एक key सिर्फ एक organisation का डेटा पढ़ सकती है, अपना। live key सिर्फ live usage देखती है और sandbox key सिर्फ sandbox usage। इन endpoints के पीछे की जाँचों में एक organisation की key को दूसरे organisation के डेटा के सामने चलाकर पक्का किया गया है कि कुछ बाहर नहीं निकलता। billing की किसी भी read से आपको यही गुण चाहिए।

नया scope क्यों नहीं बनाया

नया scope जोड़ने का मतलब होता कि बैलेंस देखने से पहले हर मौजूदा key दोबारा जारी करनी पड़ती। अपना ही बैलेंस पढ़ने से किसी और के खिलाफ key की ताकत नहीं बढ़ती, इसलिए मौजूदा verification scopes काफी हैं। अगर आपकी security policy को ऐसी key चाहिए जो सिर्फ account पढ़े और कुछ नहीं, तो support को बताएं। आज का नियम यही है कि कोई भी verification scope चलेगा।

GET /v1/account/balance: हर field का मतलब

balance का response एक JSON object है। रकम हमेशा जोड़ी में आती है: paise पूर्णांक में और rupees संख्या में, ताकि आप पैसे में हिसाब करें और रुपये में दिखाएं, बिना rounding की गलती के।

JSON
{
  "generatedAt": "2026-10-30T10:15:00.000Z",
  "environment": "LIVE",
  "sandbox": false,
  "notice": null,
  "currency": "INR",
  "balance": { "paise": 125050, "rupees": 1250.5 },
  "available": { "paise": 125050, "rupees": 1250.5 },
  "state": "OK",
  "lowBalance": false,
  "lowBalanceThreshold": { "paise": 50000, "rupees": 500 },
  "estimatedCallsRemaining": {
    "atCheapestPrice": 312,
    "cheapestProduct": { "serviceCode": "bank-account.verify", "name": "Bank account verification", "price": { "paise": 400, "rupees": 4 } },
    "atSevenDayAverage": 142,
    "sevenDayAverageCost": { "paise": 880, "rupees": 8.8 }
  },
  "lastTopUp": { "amount": { "paise": 100000, "rupees": 1000 }, "at": "2026-10-21T08:00:00.000Z" },
  "signupCredit": { "granted": { "paise": 10000, "rupees": 100 }, "left": { "paise": 0, "rupees": 0 } }
}
Fieldमतलब
generatedAtयह snapshot कब बना। यह पाँच सेकंड तक पुराना हो सकता है।
environment, sandboxsk_live_ key के लिए LIVE, sk_test_ key के लिए SANDBOX।
noticesandbox keys के लिए सूचना का पाठ, live keys के लिए null।
balancewallet में नकद। इसमें बिना खर्च हुआ signup credit भी शामिल है।
availableअभी एक call कितना खर्च कर सकती है: नकद और पात्र promotional credit। promotional credit न हो तो balance के बराबर।
stateOK, LOW_BALANCE या FINISHED।
lowBalancestate के OK न होने पर true। dashboards के लिए आसान boolean।
lowBalanceThresholdवह रकम जिसके नीचे state LOW_BALANCE बन जाती है। डिफ़ॉल्ट पाँच सौ रुपये।
estimatedCallsRemainingबैलेंस कितनी दूर चलेगा। नीचे अंदाजे वाला हिस्सा देखें।
lastTopUpसबसे नया रिचार्ज: जमा हुई मूल रकम, GST के बिना, और समय। कभी रिचार्ज नहीं किया तो null।
signupCreditमिला हुआ signup credit और उसका वह हिस्सा जो अब भी बैलेंस में बचा है।

रकम और GST

इन endpoints की हर रकम GST से पहले की है। wallet से product की कीमत कटती है, और GST हर call पर नहीं बल्कि रिचार्ज के समय लगता है। इसीलिए lastTopUp में आपको जमा हुई मूल रकम दिखती है, टैक्स समेत चुकाई कुल रकम नहीं। GST का ब्योरा आपके invoice में रहता है।

signup credit का हिसाब

नए accounts को थोड़ा signup credit मिलता है जो नकद बैलेंस में बाकी पैसों की तरह ही बैठा रहता है। ledger उसे सबसे पहले खर्च करता है, क्योंकि वह सबसे पहले जमा हुआ था। signupCredit.left उस credit का बिना खर्च हुआ हिस्सा है, जिसे बैलेंस की सीमा में रखा जाता है। एक बार शून्य होने के बाद वह शून्य ही रहता है, और top-up उसे वापस नहीं लाता। अगर किसी account को credit मिला ही नहीं, तो granted शून्य होता है।

Cache

यह snapshot StampMitra में हर organisation के लिए पाँच सेकंड cache रहता है। उस खिड़की में आई दो requests का generatedAt एक ही होता है। रिचार्ज करके नया आँकड़ा दिखने में ज्यादा से ज्यादा कुछ सेकंड लगते हैं। response में Cache-Control: private, no-store भी रहता है, जो आपके अपने proxies और browsers को बताता है कि इसकी copy न रखें।

तीन हालतें: OK, LOW_BALANCE और FINISHED

ज्यादातर integrations जिस field का सच में इस्तेमाल करेंगे, वह state है। इसे server पर निकाला जाता है, ताकि हर client को एक ही फैसला दिखे।

OK का मतलब है कि available रकम low-balance की सीमा के बराबर या ऊपर है। LOW_BALANCE का मतलब है कि वह सीमा से नीचे है लेकिन आपके लिए संभव सबसे सस्ती call से कम नहीं, यानी calls अब भी सफल होती हैं। FINISHED का मतलब है कि available रकम शून्य है या मंजूर की गई सबसे सस्ती call से छोटी है, इसलिए live call 402 के साथ लौटेगी और संदेश रिचार्ज करने को कहेगा।

हालतAvailable रकमlive calls का क्या होगाआपको क्या करना है
OKसीमा के बराबर या ऊपरसफलकुछ नहीं
LOW_BALANCEसीमा से नीचे, सबसे सस्ती call से ऊपरसफलwallet के मालिक को खबर दें, जल्दी रिचार्ज करें
FINISHEDशून्य, या सबसे सस्ती call से कम402 के साथ विफलअभी रिचार्ज करें, काम रोकें या कतार में डालें

सीमा कहाँ से आती है

डिफ़ॉल्ट सीमा पाँच सौ रुपये है। जिन accounts में मंजूर सबसे सस्ता product असामान्य रूप से महँगा है, वहाँ सीमा उस product की कीमत के दस गुना तक उठा दी जाती है, ताकि चेतावनी तब आए जब कई calls की गुंजाइश बाकी हो। असरदार संख्या lowBalanceThreshold से पढ़ें, कभी code में सीधे न लिखें।

dashboard से मेल

dashboard के header का wallet chip और low-balance वाला email भी यही तीन हालतें इस्तेमाल करते हैं। नाम थोड़े अलग हैं: dashboard READY और NEEDS_RECHARGE कहता है, जहाँ API OK और FINISHED कहती है। दोनों एक ही स्थिति बताते हैं।

कितनी calls बची हैं: सबसे सस्ती कीमत और सात दिन का औसत

रुपयों में बैलेंस देखकर कोई engineer नहीं बता सकता कि कितनी verifications बाकी हैं। estimatedCallsRemaining वाला हिस्सा पैसे को calls में दो तरह से बदलता है।

atCheapestPrice available रकम को उस सबसे सस्ते product की कीमत से भाग देता है जिसका इस्तेमाल करने की आपको मंजूरी है। यह आशावादी आँकड़ा है: अगर आप सिर्फ वही product चलाएं तो इतनी calls आएंगी। cheapestProduct उस product और उसकी कीमत का नाम देता है ताकि आप धारणा दिखा सकें।

atSevenDayAverage available रकम को पिछले सात दिनों के live traffic में प्रति call औसत billed कीमत से भाग देता है, इसलिए इसमें आपके असली product मिश्रण की झलक होती है। sevenDayAverageCost वही औसत दिखाता है। पिछले सात दिनों में कोई billed call न हो तो दोनों null हैं, और तब सबसे सस्ती कीमत वाले आँकड़े पर लौटें।

दोनों संख्याएँ साथ पढ़ें

औसत वाले आँकड़े को योजना की संख्या मानें और सस्ती कीमत वाले को ऊपरी सीमा। दोनों में बड़ा फासला हो तो आपका traffic महँगे products पर चल रहा है। हफ्ते भर में औसत वाला आँकड़ा घटता जाए तो या तो volume बढ़ रहा है या traffic महँगे lookups की तरफ खिसक रहा है। न कीमत में बदलाव इनमें गिना जाता है, न वह traffic जो आपने अभी भेजा ही नहीं। ये अंदाजे हैं, और इन्हें अंदाजा ही कहा गया है।

जब आँकड़े null हों

जब organisation के लिए कोई product मंजूर और कीमत वाला न हो, जैसे वह account जिसने production onboarding पूरी नहीं की, तब atCheapestPrice null होता है। endpoint कभी कोई कीमत गढ़ता नहीं। null दिखे तो बैलेंस को बिना अंदाजे के दिखाएं।

GET /v1/account/usage: चालू और पिछला महीना

usage का response दो महीनों के block, आज के block और आप पर लागू सीमाओं से बना है। महीनों के block की बनावट एक जैसी है, इसलिए आपका एक ही function दोनों को दिखा सकता है।

JSON
{
  "generatedAt": "2026-10-30T10:15:00.000Z",
  "environment": "LIVE",
  "sandbox": false,
  "notice": null,
  "timezone": "Asia/Kolkata",
  "currentMonth": {
    "month": "2026-10",
    "from": "2026-09-30T18:30:00.000Z",
    "to": "2026-10-30T10:15:00.000Z",
    "gstIncluded": false,
    "requests": 1840,
    "billedRequests": 1712,
    "failedNotBilled": 101,
    "successNotBilled": 0,
    "pendingBilling": 27,
    "spend": { "paise": 684800, "rupees": 6848 },
    "byProduct": [
      { "serviceCode": "pan.verify", "name": "PAN verification", "requests": 1500, "billedRequests": 1400, "failedNotBilled": 90, "successNotBilled": 0, "pendingBilling": 10, "spend": { "paise": 560000, "rupees": 5600 } }
    ],
    "daily": [
      { "date": "2026-10-29", "requests": 120, "billedRequests": 112, "failedNotBilled": 8, "successNotBilled": 0, "pendingBilling": 0, "spend": { "paise": 44800, "rupees": 448 } }
    ]
  },
  "previousMonth": { "month": "2026-09", "...": "currentMonth जैसी ही बनावट" },
  "today": {
    "date": "2026-10-30",
    "requests": 64,
    "billedRequests": 60,
    "failedNotBilled": 4,
    "spend": { "paise": 24000, "rupees": 240 },
    "requestsPerDay": { "limit": null, "used": 64, "remaining": null }
  },
  "limits": {
    "requestsPerMinute": { "limit": 60, "source": "PLAN" },
    "requestsPerDay": { "limit": null, "source": "NONE" }
  }
}

byProduct में सबसे व्यस्त product सबसे ऊपर रहता है। daily में खाली दिन भी जुड़े होते हैं: हर भारतीय कैलेंडर दिन मौजूद है, चाहे उस दिन traffic शून्य रहा हो, इसलिए chart को खाली जगहों का अंदाजा नहीं लगाना पड़ता। चालू महीने के लिए श्रृंखला पहले दिन से आज तक चलती है, और पिछले महीने के लिए पूरे महीने की।

आँकड़े किस पर टिके हैं

usage उस request record से आता है जो StampMitra metered product routes की calls के लिए रखता है: verification, e-Stamp और e-Sign। valid key के साथ API तक पहुँची हर call एक बार दर्ज होती है, उन calls समेत जो provider तक पहुँचने से पहले रोक दी गईं, जैसे 402 या 429। account के अपने endpoints गिने नहीं जाते, इसलिए poll करने से आपका usage नहीं फूलता।

कितने दिन का record

call records कम से कम नब्बे दिन database में रहते हैं, इसलिए चालू और पिछला महीना हमेशा पूरे होते हैं। usage endpoint जानबूझकर सिर्फ इन्हीं दो महीनों को कवर करता है। पुराने इतिहास के लिए अपने invoices और request log वाला endpoint इस्तेमाल करें।

requests कैसे गिनी जाती हैं: billed, failed और pending

गिनी गई हर call चार समूहों में से ठीक एक में आती है, और समूहों का जोड़ कुल के बराबर बैठता है। finance की टीमें सबसे पहले यही गुण जाँचती हैं, इसलिए यह गारंटी है।

समूहनियम
billedRequestscall का बिल बना। इसमें वह दुर्लभ quotation नियम भी आता है जो किसी खास failed नतीजे का बिल लगाता है।
pendingBillingdebit लगना बाकी है और जल्दी निपट जाएगा। इसकी रकम अभी spend में नहीं है।
failedNotBilledHTTP status 400 या उससे ऊपर था और बिल नहीं बना। provider से पहले रुकी calls भी इसमें हैं।
successNotBilledHTTP status 400 से नीचे था और बिल नहीं बना, जैसे sandbox call या बिना कीमत वाला product।

यानी requests = billedRequests + pendingBilling + failedNotBilled + successNotBilled।

failed calls का बिल क्यों नहीं बनता

verification का बिल सफलता पर बनता है। गलत format वाला PAN जो validation में गिरा, खाली बैलेंस की वजह से लौटाई गई call, rate limiter से रुकी call और ऐसी call जहाँ upstream service तक पहुँचा ही न जा सका, इनका बिल नहीं बनता। ये failedNotBilled में दिखती हैं ताकि आप देख सकें कि कितना traffic बिना नतीजे के गया। इसका हिस्सा ऊँचा हो तो जाँच करें: अक्सर इसका मतलब होता है कि भेजने से पहले inputs validate नहीं हो रहे, या कोई सीमा बार-बार छू रही है।

खर्च

spend billed calls की रकमों का जोड़ है, GST से पहले। pending debits इसमें नहीं हैं। जिस दिन pending calls दिख रही हों, उसका खर्च उनके निपटने के बाद दोबारा पढ़ने पर थोड़ा ऊँचा दिखेगा।

invoices से मिलान

यहाँ का खर्च price book का खर्च है, यानी वही मात्रा जो wallet को हिलाती है। invoices रिचार्ज और plan fee पर बनते हैं और उनमें GST होता है, इसलिए एक महीने के usage खर्च और एक महीने के invoices का जोड़ बराबर नहीं होगा। engineering और operations के सवालों के लिए usage, और टैक्स के लिए invoices देखें।

भारतीय दिन, महीने और उनकी सीमा का महत्व

दिन और महीने की सीमाएँ भारतीय मानक समय में हैं, यानी UTC से साढ़े पाँच घंटे आगे, और daylight saving नहीं। तीस तारीख को रात 23:59:59 IST पर हुई call पुराने महीने की है। पहली तारीख को 00:00:00 IST पर हुई call नए महीने की। UTC में देखें तो IST की आधी रात एक शाम पहले 18:30 बजे होती है।

यही ब्योरा तय करता है कि देर रात की call किस महीने में गिरे, इसलिए response में इस्तेमाल हुए क्षण भी दिखाए जाते हैं। महीने का from उसका पहला क्षण है UTC में, जैसे अक्टूबर के लिए 2026-09-30T18:30:00.000Z। timezone field हर response में Asia/Kolkata कहता है।

महीने और साल का बदलना

endpoint का मतलब हमेशा उस कैलेंडर महीने से है जिसमें भारत का मौजूदा क्षण पड़ता है। भारत में नए महीने के पहले कुछ घंटों में UTC के हिसाब से अब भी पिछला महीना चल रहा होता है, और endpoint तब भी नया महीना बता देता है। previousMonth भी उसी के साथ खिसकता है, और साल बदलने पर जनवरी का पिछला महीना पिछले साल का दिसंबर होता है।

आज

today block सिर्फ मौजूदा भारतीय दिन है। इसे रोज के बजट alarm के लिए इस्तेमाल करें। यह पिछले चौबीस घंटों वाली खिसकती खिड़की नहीं है।

chart के लिए सुझाव

daily श्रृंखला की date strings जैसी हैं वैसी ही इस्तेमाल करें। browser में उन्हें स्थानीय timezone में parse करने से कुछ timezones में दिन एक खिसक सकता है। उन्हें सादी तारीख की तरह दिखाएं।

Rate limit वाले headers

जो routes rate limiter से गुजरते हैं, वे हर response पर, सफल हो या नहीं, तीन headers भेजते हैं।

HeaderValue
X-RateLimit-Limitचालू एक मिनट की खिड़की में इजाजत वाली requests की संख्या।
X-RateLimit-Remainingइस request के बाद उस खिड़की में कितनी बची हैं। शून्य से नीचे कभी नहीं।
X-RateLimit-Resetखिड़की खत्म होने और counter के फिर से शुरू होने में बचे पूरे सेकंड, एक से साठ के बीच।

ये संख्याएँ घड़ी के मिनट से जुड़ी तय खिड़की बताती हैं, इसलिए reset वाली value मिनट बीतने के साथ घटती है और अगली सीमा पर वापस उछलती है। remaining नीचे गिनता जाता है, और जो request तब आती है जब remaining शून्य है, वही असफल होती है।

कौन सी सीमा बताई जाती है

एक call दो गिनतियों से गुजर सकती है: route की अपनी सीमा, और आपके plan की सीमा जो आपकी सभी keys और सभी verification routes में साझा है। दोनों लागू हों तो headers उसे बताते हैं जिसमें जगह कम बची हो, क्योंकि पहले वही काटेगी। verification routes पर सीमा आपके plan की requests per minute है, और usage endpoint भी उसे limits.requestsPerMinute में बताता है।

Retry-After

जब rate limiter किसी call को 429 से लौटाता है, तब response में सेकंडों में Retry-After भी रहता है, जो reset वाली value के बराबर है। अगर response में पहले से Retry-After था, तो मौजूदा value को छुआ नहीं जाता। जो 429 rate limiter से नहीं आता, जैसे नए खुले account पर महीने की कोई सीमा, उस पर गढ़ा हुआ Retry-After नहीं जोड़ा जाता।

headers का इस्तेमाल

जो client सिर्फ 429 पर प्रतिक्रिया देता है, वह हर बार छत से टकराकर एक request खोता है। जो client X-RateLimit-Remaining पढ़ता है, वह संख्या किसी मार्जिन से नीचे जाते ही, जैसे सीमा का दस प्रतिशत, अपना worker pool धीमा कर सकता है और reset के बाद फिर तेज। नीचे के code नमूनों में यह तरीका दिया है।

Wallet के headers: X-Wallet-State और X-Wallet-Balance-Low

live keys को authenticated calls पर wallet headers मिलते हैं।

X-Wallet-State में OK, LOW_BALANCE या FINISHED आता है, वही value जो balance endpoint बताता है। X-Wallet-Balance-Low की value true सिर्फ तब भेजी जाती है जब बैलेंस कम हो, यानी state LOW_BALANCE या FINISHED हो। यह कभी false बनकर नहीं आता: इसका न होना ही कम न होने का संकेत है।

इन headers का मकसद बिना खर्च की जागरूकता है। हर verification response वैसे भी आपके code से गुजरता है, इसलिए वहाँ कम बैलेंस भाँप लेना मुफ्त है, किसी अतिरिक्त call के बिना। बैलेंस के सीमा लाँघने के उसी मिनट में header alert उठा सकता है।

सही रकम कभी header में नहीं

यह जानबूझकर लिया गया फैसला है। headers reverse proxy के logs, load balancer के logs, observability tools और कभी-कभी browser tools में नकल हो जाते हैं। header में बैलेंस होता तो एक व्यावसायिक रूप से संवेदनशील संख्या रास्ते के हर सिस्टम तक पहुँच जाती। state उतना ही बताती है जितना client को चाहिए। रकम चाहिए तो किसी भरोसेमंद backend से TLS पर balance endpoint को call करें।

headers गायब भी हो सकते हैं

wallet की हालत StampMitra के servers की memory में रहती है और उस बैलेंस से ताजा होती है जिसे metering का चरण पहले से पढ़ता है। verification call के लिए वह तुरंत उपलब्ध होती है। बाकी routes पर, किसी ताजा restart हुए server पर किसी organisation की पहली call में वह न आए, ऐसा हो सकता है, क्योंकि StampMitra उसे लाने के लिए आपका जवाब रोकेगा नहीं। wallet headers को संकेत मानें। गायब हों तो कुछ न करें, और पक्की जानकारी चाहिए तो balance endpoint को call करें।

किस route पर कौन सा header आता है

headers /v1 के नीचे की authenticated calls में जुड़ते हैं, जहाँ authenticated का मतलब valid key है। नीचे की तालिका बताती है कि क्या उम्मीद रखें।

CallX-RateLimit-*Retry-AfterX-Wallet-State और X-Wallet-Balance-Low
सभी POST /v1/verify/* routes, live keyहाँ, plan की सीमा429 परजानकारी हो तो हाँ
सभी POST /v1/verify/* routes, sandbox keyहाँ, sandbox की सीमा429 परनहीं
GET /v1/account/balance और /usage, live keyहाँ, मिनट में साठ429 परजानकारी हो तो हाँ
GET /v1/account/balance और /usage, sandbox keyहाँ, मिनट में बारह429 परनहीं
अपनी सीमा वाले routes, जैसे wallet top-upहाँ, वही सीमा429 परlive keys के लिए जानकारी हो तो हाँ
rate limiter के बिना authenticated routesनहींनहींlive keys के लिए जानकारी हो तो हाँ
key न हो या गलत हो (401)नहींनहींनहीं

error responses भी गिनी जाती हैं

headers तब लिखे जाते हैं जब response शुरू होता है, इसलिए वे errors के साथ भी जाते हैं। खाली wallet पर 402 के साथ, बिना बदली 402 body के बगल में, X-Wallet-State: FINISHED होता है। 429 में reset की जानकारी रहती है। गलत PAN पर 400 में वही rate limit जानकारी रहती है जो 200 में होती।

क्या कभी नहीं बदलता

body, status codes, error codes और हर मौजूदा header पहले जैसे हैं। जिस response की body नए headers के बिना एक लंबाई की है, वही body उनके साथ भी वैसी ही है।

बंद करने का स्विच

StampMitra नए headers को बिना deployment के बंद कर सकता है। बंद होने पर कोई response उन्हें नहीं ले जाता, जबकि दोनों नए endpoints चलते रहते हैं। यह उस दुर्लभ स्थिति का सुरक्षा वाल्व है जब कोई बीच की कड़ी अनजान headers पर गड़बड़ करे। headers को वैकल्पिक मानकर code लिखने की यह एक और वजह है।

Sandbox keys

sandbox key असली बैलेंस कभी नहीं देखती। sk_test_ key से GET /v1/account/balance का जवाब होता है environment: "SANDBOX", sandbox की सूचना, state OK और हर रकम शून्य। इस request के लिए कोई wallet पढ़ा ही नहीं जाता। कारण सीधा है: sandbox calls मुफ्त हैं और नमूना डेटा लौटाती हैं, इसलिए खर्च करने को कुछ है ही नहीं।

sandbox key से GET /v1/account/usage आपकी sandbox calls गिनता है, खर्च हमेशा शून्य, और सूचना समझाती है कि ये sandbox की calls हैं। live key sandbox calls कभी नहीं देखती, और sandbox key live calls कभी नहीं, भले दोनों एक ही organisation की हों।

sandbox keys को route की production सीमा का पाँचवाँ हिस्सा मिलता है, कम से कम एक request प्रति खिड़की। account endpoints के लिए यह मिनट में बारह है, जबकि live keys के लिए साठ। Verification, e-Sign और e-Stamp calls की sandbox key पर अलग सीमा है: प्रति organisation प्रति मिनट 10 और प्रति दिन 200 requests। हर e-Stamp sandbox request इस कोटे में गिनी जाती है, catalogue पढ़ना, order और stamp की जाँच और दोनों sandbox wallets समेत, और sample-certificate के download link की अपनी सीमा है, प्रति IP address प्रति घंटा 60। usage endpoint दोनों को limits.requestsPerMinute और limits.requestsPerDay में SANDBOX source के साथ बताता है, और today.requestsPerDay.used दिखाता है कि आज की 200 में से कितनी इस्तेमाल हुईं। दिन आधी रात IST पर रीसेट होता है।

sandbox के responses में rate limit headers रहते हैं और wallet के बारे में कुछ नहीं। अगर आपके client को कोई wallet header दिखे, तो वह production से बात कर रहा है। कुछ teams इसे tests में पहरेदार की तरह इस्तेमाल करती हैं: जिस test को response में X-Wallet-State मिले, उसने गलती से live key चला दी है।

ग्राहक सिस्टम के लिए कम बैलेंस का सुझाया तरीका

मकसद यह है कि जो लोग रिचार्ज कर सकते हैं उन्हें जल्दी खबर मिले, और अगर वे न करें तो सिस्टम काबू में रहकर धीमा पड़े। चार परतें साथ में अच्छा काम करती हैं।

पहली परत: तय समय पर जाँच

हर पाँच मिनट में एक छोटा job चलाएं। वह GET /v1/account/balance को call करे, state और available paise को metrics में डाले, और पिछली बार वाली state से मिलाए। alert हर बार नहीं, बदलाव पर उठे: OK से LOW_BALANCE पर finance या platform के channel में चेतावनी, LOW_BALANCE से FINISHED पर page। रिचार्ज के बाद state OK पर लौटे तो "सुलझ गया" वाला संदेश जाए, ताकि इंसान को पता चले कि इलाज चल गया।

दूसरी परत: hot path में header पढ़ना

जो code पहले से verification call करता है, उसमें हर response का X-Wallet-State पढ़ें और ताजा value को साझा variable या cache key में रखें। FINISHED या LOW_BALANCE दिखे तो अगली तय जाँच का इंतजार किए बिना alert का तर्क जल्दी चला दें। यह कुछ पंक्तियाँ हैं और इसका कोई खर्च नहीं।

तीसरी परत: गैर-जरूरी काम के लिए circuit

अपने verification काम को जरूरी और टाले जा सकने वाले में बाँटें। signup screen पर इंतजार करता ग्राहक जरूरी है। पुराने records की रात वाली दोबारा verification टाली जा सकती है। state LOW_BALANCE हो तो जरूरी flows चलने दें और टाले जा सकने वाले रोक दें। FINISHED हो तो जो जरूरी requests रुक सकती हैं उन्हें कतार में डालें, जो नहीं रुक सकतीं उनके लिए user को साफ संदेश दिखाएं, और ऐसी calls भेजना बंद करें जो पक्का असफल होंगी।

चौथी परत: कितने दिन चलेगा

available paise को usage endpoint के औसत दैनिक खर्च से भाग देकर बचे दिन निकालें। state चाहे जो हो, सात दिन, तीन दिन और एक दिन पर alert दें। जो wallet आज OK है लेकिन रोज एक दिन का traffic खा रहा है, वह OK नहीं रहेगा, और runway वाला alert सीमा वाले alert से पहले बजता है।

संकेतसीमाकार्रवाई
बचे दिनसात दिनसुझाई रिचार्ज रकम के साथ finance को बताएं
state का LOW_BALANCE होनाकोई भीमालिक को चेतावनी, टालने लायक jobs रोकें
state का FINISHED होनाकोई भीpage करें, जरूरी काम कतार में डालें, साफ संदेश दिखाएं
state का OK पर लौटनाकोई भीalert बंद करें, रोके गए jobs चलाएं

alert की थकान से बचाव

state बदलने पर alert दें और हर स्तर पर एक घंटे का ठंडा समय रखें। balance endpoint सस्ता है, लेकिन सीमा के आसपास डोलता बैलेंस, top-ups और भारी traffic के साथ, state को आगे-पीछे कर सकता है। resolved मानने से पहले state को लगातार दो जाँचों तक टिकने देना channel को शांत रखता है।

रिचार्ज का जिम्मेदार

एक नाम तय करें। बीस लोगों वाले channel में गया कम बैलेंस alert कोई नहीं पढ़ता। alert के पाठ में एक व्यक्ति और एक विकल्प का नाम रखें, और dashboard से रिचार्ज का link दें। अगर आपकी finance प्रक्रिया को पहले payment link या invoice चाहिए तो support मदद कर सकता है।

cURL के उदाहरण

live key से balance पढ़ें:

cURL
curl -s https://api-b2b.stampmitra.in/v1/account/balance \
  -H "Authorization: Bearer $STAMPMITRA_LIVE_KEY"

usage पढ़ें और jq से चालू महीने का खर्च निकालें:

cURL
curl -s https://api-b2b.stampmitra.in/v1/account/usage \
  -H "Authorization: Bearer $STAMPMITRA_LIVE_KEY" \
  | jq '{month: .currentMonth.month, requests: .currentMonth.requests, spendRupees: .currentMonth.spend.rupees}'

verification call के headers देखें, body छापे बिना, ताकि सीमा और wallet की हालत दिखे:

cURL
curl -s -o /dev/null -D - https://api-b2b.stampmitra.in/v1/verify/pan \
  -H "Authorization: Bearer $STAMPMITRA_LIVE_KEY" \
  -H "Content-Type: application/json" \
  -d '{"pan":"ABCDE1234F"}' | grep -i -E "^(x-ratelimit|x-wallet|retry-after)"

cron के लिए एक पंक्ति

यह एक पंक्ति wallet के OK न होने पर शून्य से अलग exit code के साथ बंद होती है, जो cron job या CI की सेहत जाँच को जमता है:

cURL
curl -s https://api-b2b.stampmitra.in/v1/account/balance -H "Authorization: Bearer $STAMPMITRA_LIVE_KEY" | jq -e '.state == "OK"' > /dev/null

Python में पूरा उदाहरण

Python संस्करण requests इस्तेमाल करता है। इसमें usage endpoint से बचे दिनों का हिसाब भी है, जो सबसे काम की पूर्व चेतावनी है।

Python
import os
import time
import requests

BASE = "https://api-b2b.stampmitra.in"
HEADERS = {"Authorization": f"Bearer {os.environ['STAMPMITRA_LIVE_KEY']}"}


def get_json(path):
    r = requests.get(f"{BASE}{path}", headers=HEADERS, timeout=10)
    r.raise_for_status()
    return r.json()


def runway_days():
    balance = get_json("/v1/account/balance")
    usage = get_json("/v1/account/usage")
    days = [d for d in usage["currentMonth"]["daily"] if d["requests"] > 0]
    if not days:
        return None, balance
    average_paise = sum(d["spend"]["paise"] for d in days) / len(days)
    if average_paise <= 0:
        return None, balance
    return balance["available"]["paise"] / average_paise, balance


def verify_pan(pan, retries=3):
    for attempt in range(retries + 1):
        r = requests.post(f"{BASE}/v1/verify/pan", headers=HEADERS, json={"pan": pan}, timeout=15)
        if r.headers.get("X-Wallet-State") in ("LOW_BALANCE", "FINISHED"):
            print("wallet कम है:", r.headers["X-Wallet-State"])  # यहाँ अपना alert लगाएं
        if r.status_code == 429 and attempt < retries:
            time.sleep(int(r.headers.get("Retry-After", "5")) + 0.5)
            continue
        if r.status_code == 402:
            raise RuntimeError("wallet खत्म: दोबारा कोशिश से पहले रिचार्ज करें")
        r.raise_for_status()
        return r.json()


if __name__ == "__main__":
    days, bal = runway_days()
    print(bal["state"], "बचे दिन:", None if days is None else round(days, 1))

बचे दिन पढ़ने का तरीका

यह function बिना traffic वाले दिन छोड़ देता है ताकि शांत सप्ताहांत औसत को अच्छा न दिखा दे। सावधान रहना चाहें तो औसत की जगह हाल का सबसे व्यस्त दिन लें। दोनों हालत में alert रुपयों पर नहीं, दिनों की संख्या पर लगाएं: सात दिन का runway हर आकार के account के लिए एक ही बात कहता है।

JavaScript में छोटा सा helper

Node 18 या उसके बाद के बिल्ट-इन fetch के साथ यह बिना dependency वाला नमूना alert के लिए state का बदलाव पकड़ता है और headers से रफ्तार तय करता है।

JavaScript
const BASE = "https://api-b2b.stampmitra.in";
const KEY = process.env.STAMPMITRA_LIVE_KEY;
let last = "OK";

async function checkWallet(notify) {
  const res = await fetch(`${BASE}/v1/account/balance`, { headers: { Authorization: `Bearer ${KEY}` } });
  if (!res.ok) throw new Error(`balance ${res.status}`);
  const b = await res.json();
  if (b.state !== last) {
    await notify(`wallet ${last} -> ${b.state}, बची calls लगभग ${b.estimatedCallsRemaining.atSevenDayAverage ?? "अज्ञात"}`);
    last = b.state;
  }
  return b;
}

function pace(res) {
  const limit = Number(res.headers.get("x-ratelimit-limit"));
  const remaining = Number(res.headers.get("x-ratelimit-remaining"));
  return limit && remaining < limit * 0.1 ? 250 : 0; // सीमा के पास आएं तो धीमे चलें
}

module.exports = { checkWallet, pace };

असली client में 429 पर दोबारा कोशिश की गिनती और समय-सीमा जरूर जोड़ें, जैसा API errors और handling में बताया है।

429 और 402 को सही तरह संभालना

दोनों errors retry वाले loop को एक जैसे दिखते हैं, पर उनका इलाज उलटा है।

rate limiter का 429 अस्थायी है। Retry-After तक रुकें, थोड़ा jitter जोड़ें ताकि workers का झुंड एक साथ न लौटे, कोशिशों की गिनती तय रखें और concurrency घटाएं। 429 नियमित दिखे तो बेहतर इलाज X-RateLimit-Remaining से रफ्तार तय करना है, या plan की ऊँची सीमा। plan की सीमाएँ pricing पेज पर हैं।

402 अस्थायी नहीं है। 402 को दोहराने से वही failure दोहरता है और ऊपर से आपके logs में बाढ़ आती है। रुकें, alert उठाएं, जो रुक सकता है उसे कतार में डालें, और state के OK या LOW_BALANCE पर लौटने के बाद ही आगे बढ़ें। 402 वाले response के wallet headers FINISHED कहते हैं, जो आपके code को message के पाठ से मिलान किए बिना साफ कारण देता है।

संदेश को parse न करें

संदेश इंसानों के लिए हैं और बदले जा सकते हैं। तर्क के लिए status code, error envelope का code और balance endpoint के state वाले fields इस्तेमाल करें।

account के endpoints भी 429 दे सकते हैं

मॉनिटर के लिए मिनट में साठ requests काफी हैं, पर loop के लिए कम। हर सेकंड poll करने वाला job एक मिनट बाद लौटा दिया जाएगा। मिनट में एक बार या उससे धीमे poll करें।

Cache, polling और endpoints की अपनी सीमाएँ

दोनों endpoints सस्ती reads हैं, और उनकी हिफाजत भी सस्ती reads की तरह होती है। हर key उन पर मिनट में साठ requests कर सकती है, sandbox keys बारह। उनका अपना counter है, verification routes के plan वाले हिस्से से अलग, इसलिए बैलेंस पढ़ना verification traffic से कभी रुक नहीं सकता और verification की क्षमता कभी खर्च नहीं करता।

balance का snapshot पाँच सेकंड और usage का snapshot तीस सेकंड cache रहता है। इससे तेज poll करने पर वही डेटा लौटता है। समझदार तालिका है: balance के लिए एक मिनट और usage के लिए पाँच मिनट। जो dashboards user की कार्रवाई पर refresh होते हैं वे जरूरत पर call कर सकते हैं।

एक साथ आई requests

caches एक साथ आई requests को जोड़ देते हैं: एक ही organisation की दस requests साथ आएं तो हिसाब एक बार चलता है। आपका अपना cache फिर भी काम का है, खासकर बहु-ग्राहक application में जहाँ एक backend एक ही पन्ना देखते कई कर्मचारियों को जवाब देता है।

विफलता में व्यवहार

अगर StampMitra उस पल आपका डेटा न पढ़ सके, तो endpoints ACCOUNT_DATA_UNAVAILABLE code के साथ 503 लौटाते हैं। balance के वैकल्पिक हिस्से, जैसे आखिरी top-up या अंदाजे, पूरा response गिराने की जगह null पर लौट जाते हैं। 503 को अस्थायी मानें और अपने मॉनिटर में आखिरी अच्छी value रखें।

Security और privacy के पहलू

बैलेंस को व्यावसायिक रूप से संवेदनशील मानें। endpoints को backend से call करें, कभी browser या mobile app से नहीं, क्योंकि उसके लिए API key को client तक भेजना पड़ेगा। keys को कैसे रखें और घुमाएं, यह API security policy में है।

wallet headers को ग्राहक के सामने जाने वाली किसी चीज में न जाने दें। state हानिरहित है, पर उसे end user के browser तक पहुँचाने का कोई कारण नहीं। responses को proxy करते हुए अपने edge पर custom headers हटा दें।

failures का requestId log करें, और key कभी log न करें। नए endpoints आपके end users का कोई व्यक्तिगत डेटा नहीं लौटाते, सिर्फ organisation स्तर के जोड़ लौटाते हैं। usage के आँकड़े आपके कारोबार का आकार जरूर बताते हैं, इसलिए जिन dashboards में वे जाएं उन्हें देखने वाले सीमित रखें।

कम से कम अधिकार

अगर आपकी policy माँगती है तो मॉनिटरिंग के लिए अलग key रखें। उसे एक ही verification scope दें, जो account endpoints के लिए काफी है, और उसे application वाली key से अलग रखें। मॉनिटरिंग key लीक हो भी जाए तो वह आपका बैलेंस पढ़ सकती है, उस एक product की call से महँगा कुछ नहीं।

IP की अनुमति सूची

अगर आपकी keys कुछ IP addresses तक सीमित हैं, तो मॉनिटरिंग job भी अनुमत पते से चले। IP की रोक वाला 403 INSUFFICIENT_SCOPE वाली scope की गलती से अलग दिखता है, और संदेश बताता है कि आप किससे टकराए।

Sandbox में जाँच और live जाने की तैयारी

sandbox key से शुरू करें। balance endpoint को call करके पक्का करें कि sandbox की सूचना और शून्य रकम मिलती हैं। किसी verification route को call करें और rate limit headers देखें। जो code X-Wallet-State पढ़ता है उसे चलाएं, लेकिन याद रखें कि sandbox में वह नहीं दिखेगा, इसलिए alert और circuit को परखने के लिए unit test में अपने handler को नकली FINISHED value दें।

live key पर जाने से पहले की सूची

  1. तय समय वाली balance जाँच live key से चलती है और असली channel में alert भेजती है।
  2. alert के पाठ में मालिक और विकल्प का नाम है।
  3. state LOW_BALANCE होने पर टालने लायक jobs रोके जाने का flag मानते हैं।
  4. FINISHED पर जरूरी flows साफ संदेश दिखाते हैं और 402 को दोहराते नहीं।
  5. आपका client हर नए header को वैकल्पिक मानता है और सब गायब हों तब भी चलता है।
  6. chart का code daily श्रृंखला की तारीखें बिना timezone बदले इस्तेमाल करता है।
  7. मॉनिटरिंग job साठ requests प्रति मिनट की सीमा से काफी नीचे रहता है।

कम बैलेंस का पूर्वाभ्यास

असली wallet को मनचाहे समय पर कम नहीं किया जा सकता, और जाँचने के लिए पैसे खर्चने भी नहीं चाहिए। नकल करें: staging में balance endpoint को पहले LOW_BALANCE और फिर FINISHED लौटाने वाला बनाएं और देखें कि आपके alerts, कतारें और संदेश कैसे चलते हैं। हर environment के फर्क समझने के लिए sandbox और production keys वाली गाइड देखें।

दिक्कत आए तो

wallet headers कभी दिखते ही नहीं। पक्का करें कि आप live key इस्तेमाल कर रहे हैं। sandbox keys को ये कभी नहीं मिलते। देखें कि call authenticated थी और verification जैसे route से गुजरी। ताजा restart हुए server पर metering के बिना route की पहली call में ये गायब हो सकते हैं। आपकी किसी भी call पर ये कभी न आएं तो हो सकता है इन्हें operationally बंद किया गया हो; balance endpoint फिर भी चलता है।

किसी route पर rate limit headers नहीं हैं। सिर्फ rate limiter इस्तेमाल करने वाले routes इन्हें भेजते हैं। ऊपर की routes वाली तालिका से मिलाएं।

balance endpoint पर INSUFFICIENT_SCOPE। key के पास कोई verification scope नहीं है। कम से कम एक वाली key जारी करें या मौजूदा production key इस्तेमाल करें।

बैलेंस पुराना लगता है। snapshot पाँच सेकंड पुराना हो सकता है। रिचार्ज के बाद कुछ सेकंड रुकें। मिनटों तक गलत रहे तो अपनी call का requestId support को भेजें।

usage के जोड़ मेरी अपनी गिनती से नहीं मिलते। usage valid keys वाली, metered product routes पर दर्ज calls को भारतीय दिन के हिसाब से गिनता है। फर्क timezone के कटाव से आता है (आपकी गिनती UTC में हो सकती है), उन retries से जिन्हें आप एक बार और हम दो बार गिनते हैं, और सीमाओं से रुकी उन calls से जिनका नतीजा आपके code ने कभी नहीं देखा। billed, pending, failed और बिना बिल सफल calls का विभाजन फासला ढूँढने में मदद करता है।

spend wallet की हलचल से कम है। pending debits निपटने तक spend में नहीं आते। कुछ मिनट बाद दोबारा पढ़ें।

account endpoints पर 429 मिल रहा है। poll मिनट में एक बार तक धीमा करें।

ACCOUNT_DATA_UNAVAILABLE के साथ 503। अस्थायी विफलता। थोड़ी देर बाद दोबारा कोशिश करें और पिछली value रखें।

support को क्या भेजें

error body का requestId, भारतीय समय में अंदाजन वक्त, endpoint और आपने क्या सोचा था। पूरी key कभी न भेजें; key के पहले बारह अक्षर, यानी prefix, पहचान के लिए काफी हैं।

StampMitra आपकी कैसे मदद करता है

StampMitra, Bani Global Industries LLP का चलाया LegalTech platform है। यह कोई सरकारी एजेंसी नहीं है, और ये endpoints आपकी किसी कानूनी या अनुपालन जिम्मेदारी को नहीं बदलते। ये आपके engineers और finance के लोगों को वही तथ्य देते हैं जो dashboard दिखाता है, ऐसे रूप में जिसे code पढ़ सके।

आज आप API key से बैलेंस और usage पढ़ सकते हैं, authenticated calls पर rate limit और wallet की हालत के संकेत पा सकते हैं, requests आजमाने के लिए Postman collection या OpenAPI document import कर सकते हैं, और दोनों नए operations समझने वाले typed clients के लिए SDK पन्ने देख सकते हैं। verification docs हर वह product गिनाते हैं जिसका भुगतान wallet से हो सकता है, और PAN verification की गाइड पहला पूरा integration दिखाती है।

इस सुविधा की ईमानदार सीमाएँ: आज accounts पर प्रतिदिन requests की कोई सीमा लागू नहीं है, इसलिए usage response में प्रतिदिन की सीमा null है और उसका source NONE कहता है; usage दो महीने कवर करता है, लंबा इतिहास नहीं; wallet headers संकेत हैं, गारंटी नहीं; और इन endpoints से बैलेंस पढ़ा जाता है, बदला नहीं जाता। रिचार्ज dashboard या wallet endpoints से होता है।

हमारा इरादा इस सतह को छोटा और स्थिर रखने का है। योजनाएँ, जो बदल सकती हैं, इनमें शामिल हैं: wallet के सीमा पार करने पर webhook जैसी सूचनाएँ ताकि poll करना वैकल्पिक हो जाए, और key-वार ज्यादा बारीक usage। इनमें से कुछ आज उपलब्ध नहीं है, और इस लेख में कुछ भी इन पर टिका नहीं है। इनमें से कोई चीज जल्दी चाहिए तो support को बताएं, क्योंकि असली integrations की माँगें ही तय करती हैं कि हम आगे क्या बनाएँ।

इस लेख की चार परतें लगा लें तो आपको कम wallet उसी घंटे पता चलेगा जब वह होगा, किसी ग्राहक की शिकायत के अगली सुबह नहीं। इन संख्याओं को खोलने का पूरा मकसद यही है।

API reference एक नज़र में

PAN

PAN: paramsPOST /v1/verify/pan

Request parameters

Request parameters
FieldTypeDescription
AuthorizationrequiredheaderBearer <api-key> (e.g. sk_test_... in sandbox, sk_live_... in production). The x-api-key header is also accepted.
panrequiredstringPAN, format ABCDE1234F.
namestringName to match against records (max 256 chars).
PAN: responsePOST /v1/verify/pan
{
  "referenceId": "SMV-20260927-8F42K7",
  "pan": "ABCDE1234F",
  "type": "Individual",
  "valid": true,
  "registeredName": "RAHUL KUMAR",
  "fatherName": "SURESH KUMAR",
  "panStatus": "VALID",
  "panStatusCode": "E",
  "panStatusDescription": "Existing and valid PAN",
  "nameMatchResult": "MATCH",
  "nameMatchScore": "100",
  "aadhaarSeedingStatus": "y",
  "aadhaarSeedingStatusDescription": "Aadhaar linked",
  "lastUpdatedAt": "2023-04-01",
  "message": "PAN is Valid"
}
PAN: pricePOST /v1/verify/pan

PAN: ₹5 per successful call, pay-as-you-go (lower on Growth and Scale).

अक्सर पूछे जाने वाले सवाल

API से अपने wallet का बैलेंस कैसे देखें?

अपनी API key के साथ account के बैलेंस वाले endpoint पर एक get request भेजें। जवाब में रुपये और पैसे में बैलेंस, कम बैलेंस की सीमा, हालत, बची calls का अंदाजा और आखिरी रिचार्ज मिलता है। नतीजा पाँच सेकंड तक cache रहता है।

कौन सी key बैलेंस और इस्तेमाल पढ़ सकती है?

जिस key के पास कोई भी verification scope या e-Stamp scope है, वह अपने ही organisation का हिसाब पढ़ सकती है। कोई नया scope नहीं बना। असंबंधित scopes वाली key को 403 मिलता है, और कोई key दूसरे organisation का डेटा कभी नहीं पढ़ सकती।

क्या सही बैलेंस किसी response header में मिलता है?

नहीं। लाइव key को wallet की हालत बताने वाला header मिलता है, और कम होने पर ही एक अलग संकेत वाला header आता है। रकम जानबूझकर header में नहीं रखी जाती, क्योंकि proxy और load balancer के logs में वह छप जाती।

rate limit के तीन header का मतलब क्या है?

पहला बताता है कि चालू मिनट में कितनी requests की इजाजत है, दूसरा बताता है कि इस request के बाद कितनी बची हैं, और तीसरा बताता है कि खिड़की खत्म होने में कितने सेकंड हैं। 429 पर रुकने का समय बताने वाला header भी उतने ही सेकंड देता है।

response में wallet वाले header कभी-कभी क्यों नहीं दिखते?

ये server की memory से आते हैं और metering के पढ़े बैलेंस से ताजा होते हैं, इसलिए StampMitra आपकी call रोककर इन्हें नहीं लाता। sandbox key को ये कभी नहीं मिलते और इन्हें operationally बंद भी किया जा सकता है। इनके बिना चलने वाला client लिखें।

महीना और दिन किस समय के हिसाब से गिने जाते हैं?

दिन और महीने भारतीय मानक समय में गिने जाते हैं, जो UTC से साढ़े पाँच घंटे आगे है। पहली तारीख की आधी रात के बाद की call नए महीने की होती है, जो UTC में एक शाम पहले साढ़े छह बजे पड़ती है। response में सटीक क्षण भी दिए जाते हैं।

क्या खर्च की रकम में GST शामिल है?

नहीं। खर्च बिल हुई calls की कीमतों का जोड़ है, GST से पहले, जो wallet को हिलाता है। GST रिचार्ज के समय लगता है और बिल पर दिखता है। हर महीने के block में एक संकेत भी है जो साफ कहता है कि टैक्स शामिल नहीं है।

sandbox key को इन endpoints से क्या मिलता है?

sandbox key को सूचना, सामान्य हालत और शून्य रकम मिलती है, और कोई wallet पढ़ा ही नहीं जाता। इस्तेमाल वाला endpoint सिर्फ sandbox की calls गिनता है, खर्च शून्य। sandbox key को इन endpoints पर मिनट में बारह requests मिलती हैं और सिर्फ rate limit header।

कम बैलेंस की चेतावनी कैसे लगानी चाहिए?

हर कुछ मिनट पर बैलेंस की जाँच चलाएं, हर बार नहीं बल्कि हालत बदलने पर चेतावनी दें, तेज पता चलने के लिए लाइव calls पर wallet वाला header पढ़ें, कम बैलेंस पर टालने लायक काम रोकें, खत्म होने पर जरूरी काम कतार में डालें और औसत खर्च से बचे दिनों की चेतावनी जोड़ें।

स्रोत

2026-10-30 को StampMitra Developers के codebase और account API के लिए StampMitra B2B platform contract से मिलाकर जाँचा गया। इस लेख के API तथ्यों के लिए किसी बाहरी वेबसाइट का इस्तेमाल नहीं हुआ।

  • GET /v1/account/balance, GET /v1/account/usage और response headers का account API contract (B2B platform repository में docs/ACCOUNT_API_CONTRACT.md), 2026-10-30 को जाँचा गया।
  • /openapi.json पर प्रकाशित OpenAPI document, संस्करण 1.1.0, operations getAccountBalance और getAccountUsage, 2026-10-30 को जाँचा गया।
  • Authentication docs: key के रूप, scopes और rate limit के नोट, 2026-10-30 को जाँचा गया।
  • API errors और handling तथा sandbox बनाम production keys, 2026-10-30 को जाँचा गया।
  • Pricing पेज: plan की सीमाएँ और product की कीमतों की सूची, 2026-10-30 को जाँचा गया।