ऑडिटर आपसे पूछता है: "इस वेंडर को तुमने अप्रैल में कैसे मंज़ूर किया था?" आपके पास जवाब में या तो तीन महीने पुराने logs का एक अधूरा टुकड़ा है, जिसमें PAN पूरा छपा है और फ़ैसले का कारण नहीं, या एक spreadsheet जिसमें लिखा है "verified"। दोनों ही जवाब कमज़ोर हैं। पहला निजी डेटा का जोखिम है और दूसरा सबूत नहीं है।
जवाब सीधा है: verification के फ़ैसले का सबूत रखिए, API ने जो कुछ बताया उसकी पूरी प्रति नहीं। हर call के लिए सबसे काम का रिकॉर्ड वह है जिसमें हो: किसने या किसने माँगा, क्या जाँचा गया (छिपाकर), कब, StampMitra का referenceId, नतीजा और वे फ़ील्ड जिन पर फ़ैसला टिका, कौन-सी नीति का संस्करण लागू था, फ़ैसला और उसके कारण, और किसी इंसान की पहचान जिसने उसे बदला। उसे उतने समय रखिए जितना आपकी नीति और क्षेत्रीय नियम माँगें। पूरे response बॉडी, application logs में असली पहचानें, या ऐसा कुछ मत रखिए जिसका कोई घोषित उद्देश्य न हो।
इस विषय में खिंचाव असली है। ऑडिटर देखना चाहता है कि फ़ैसले के समय आपको क्या पता था। निजता का ढाँचा चाहता है कि आप कम से कम निजी डेटा, कम से कम समय के लिए रखें। सुरक्षा समीक्षक चाहता है कि log aggregators में कुछ संवेदनशील न बैठे। अच्छा audit रिकॉर्ड तीनों को संतुष्ट करता है: वह छोटा है, संरचित है, जहाँ हो सके छिपा हुआ है, और नीचे की call से प्रति की जगह पहचान के ज़रिए जुड़ा है।
यह गाइड बताती है कि भारत में चलते सिस्टमों में verification call से क्या log करें और क्या रखें। यह logs को audit रिकॉर्ड से अलग करती है, न्यूनतम रिकॉर्ड परिभाषित करती है, पहचानों को छिपाना और hash करना दिखाती है, बताती है कि StampMitra के request logs कहाँ फ़िट होते हैं और उनकी सीमाएँ क्या हैं, रिटेंशन, पहुँच-नियंत्रण और छेड़छाड़ के सबूत को कवर करती है, और आपके स्टैक के किनारों पर redaction के कोड पर ख़त्म होती है। यह सामान्य मार्गदर्शन है, कानूनी सलाह नहीं। रिटेंशन की अवधियाँ और वैध आधार आपके नियामक, आपके अनुबंधों और आपके वकील पर निर्भर हैं।
मुख्य बातें
- संचालन के logs (छोटी उम्र के, डीबगिंग के लिए) और audit रिकॉर्ड (संरचित, रखे जाने वाले, सबूत के लिए) में फ़र्क़ कीजिए। उनकी सामग्री, रिटेंशन और पहुँच अलग हैं।
- audit रिकॉर्ड से आप यह बता सकें: क्या जाँचा गया, कब, किसने, क्या नतीजा, किस नीति के तहत, और क्या फ़ैसला हुआ।
- response बॉडी की नक़ल की जगह StampMitra के
referenceId(और विफलता परrequestId) से call से जुड़िए। - दिखाने और logs के लिए पहचानें छिपाइए (जैसे PAN के पहले दो और आख़िरी दो अक्षर, खाता संख्या के आख़िरी चार अंक)। जिन पहचानों की सिर्फ़ मिलान के लिए ज़रूरत है, उन्हें hash कीजिए।
- API key, पूरे PAN, पूरी खाता संख्या, पूरे response बॉडी या request बॉडी को डिफ़ॉल्ट रूप से कभी log मत कीजिए।
- StampMitra आपके organisation के लिए request logs रखता है, जो
GET /v1/logsसे पढ़े जाते हैं, और उनका रिटेंशन आपके प्लान पर निर्भर है: प्रकाशित plan डेटा में pay-as-you-go पर 30 दिन, Growth पर 90 और Scale पर 365, और sandbox पर कम। वे मूल response बॉडी नहीं लौटाते, इसलिए फ़ैसला आपके अपने रिकॉर्ड में रहना चाहिए। - रिटेंशन नीति का फ़ैसला है। क्षेत्रीय नियम KYC रिकॉर्ड वर्षों रखने को कह सकते हैं, जबकि डेटा सुरक्षा के सिद्धांत उसे मिटाने की ओर धकेलते हैं जिसकी अब ज़रूरत नहीं। अवधि अपने compliance मालिक से तय कीजिए और लिख लीजिए।
- audit रिकॉर्ड को append-only बनाइए, पढ़ने वालों को सीमित कीजिए, और छेड़छाड़ के सबूत जैसे hash chain पर विचार कीजिए।
- ऑडिट के सवाल का जवाब देने के लिए verification दोबारा चलाने से आज का जवाब मिलता है, वह नहीं जिस पर आपने भरोसा किया था। मूल रिकॉर्ड रखिए।
ऑडिट में आपसे क्या पूछा जाएगा
रिकॉर्ड की डिज़ाइन उन सवालों से उलटी तरफ़ से बनाइए जो आपसे पूछे जाएँगे।
- किसे verify किया गया, और नंबर खोले बिना हम उसे कैसे पहचान सकते हैं?
- ठीक-ठीक क्या जाँचा गया: कौन-सी पहचान, कौन-सा endpoint?
- जाँच कब की गई?
- किसने या किसने की: कौन-सी सेवा, कौन-सा यूज़र, कौन-सी key?
- स्रोत ने क्या कहा, कम से कम उन फ़ील्ड में जिन पर फ़ैसला टिका?
- फ़ैसला क्या था, और कौन-से नियमों से हुआ?
- उस समय नीति का कौन-सा संस्करण लागू था?
- क्या किसी इंसान ने स्वचालित नतीजा बदला, किसने, कब और क्यों?
- क्या हम दिखा सकते हैं कि call सचमुच हुई, आपके डेटाबेस से स्वतंत्र रूप से?
- अगर हमसे इस व्यक्ति का डेटा मिटाने को कहा जाए, तो इस रिकॉर्ड का क्या होता है?
हर सवाल नीचे के किसी फ़ील्ड या व्यवस्था से जुड़ता है। अगर रिकॉर्ड से किसी सवाल का जवाब न दे पाएँ, तो या तो फ़ील्ड जोड़िए या मान लीजिए कि आप उसका जवाब नहीं दे सकते, और नीति में यह कह दीजिए।
logs और audit रिकॉर्ड अलग चीज़ें हैं
टीमें अक्सर एक शब्द दो कामों के लिए इस्तेमाल करती हैं। उन्हें अलग कीजिए।
| संचालन का log | Audit रिकॉर्ड | |
|---|---|---|
| उद्देश्य | डीबगिंग और निगरानी | फ़ैसले का सबूत |
| सामग्री | request id, status code, समय, एरर, छिपाया विषय | विषय (छिपाकर), नतीजा, फ़ैसला, कारण, नीति का संस्करण, कर्ता, समय |
| रूप | खुली पंक्तियाँ या संरचित घटनाएँ | डेटाबेस तालिका में तय schema |
| रिटेंशन | दिन से हफ़्ते | वर्ष, जितना आपकी नीति और क्षेत्रीय नियम माँगें |
| पहुँच | इंजीनियर | compliance, ऑडिट, नामित कर्मचारियों का छोटा समूह |
| बदलाव | घुमाए और मिटाए जाते हैं | Append-only |
| निजी डेटा | जितना कम हो, आदर्श रूप से कोई नहीं | सिर्फ़ जितना फ़ैसले को चाहिए, कम और छिपाकर |
| नुक़सान सहने की क्षमता | स्वीकार्य | अस्वीकार्य |
संचालन के logs aggregators, error trackers और dashboards में जाते हैं जिन्हें कई लोग पढ़ सकते हैं और जो अक्सर तीसरे पक्षों के पास होते हैं। ठीक इसीलिए संवेदनशील डेटा वहाँ नहीं होना चाहिए। audit रिकॉर्ड नियंत्रित स्टोर में रहता है। कोई भी दूसरे की जगह नहीं ले सकता: डीबगिंग का log सबूत नहीं है, और audit रिकॉर्ड stack trace फेंकने की अच्छी जगह नहीं।
न्यूनतम verification रिकॉर्ड
नीचे का schema response बॉडी रखे बिना सवालों को कवर करता है।
| फ़ील्ड | उदाहरण | क्यों है |
|---|---|---|
id | vr_01J9... | आपकी अपनी primary key |
subject_id | vendor_1042 | आपके सिस्टम के पक्ष से कड़ी |
subject_kind | PAN, GSTIN, BANK_ACCOUNT, CIN | किस तरह की पहचान जाँची गई |
subject_masked | AB******4F | पूरा नंबर खोले बिना इंसान के पढ़ने लायक़ संदर्भ |
subject_hash | salted SHA-256 | डुप्लिकेट पहचान और असली नंबर के बिना खोज |
endpoint | POST /v1/verify/pan | क्या बुलाया गया |
environment | production | sandbox को production सबूत से कभी मत मिलाइए |
requested_at | 2026-10-29T09:41:07Z | आपने call कब की |
actor | svc:onboarding-worker या user:priya@... | किसने या किसने ट्रिगर की |
reference_id | SMV-20260927-8F42K7 | StampMitra के call-रिकॉर्ड से कड़ी |
request_id | a1b2c3d4-... | विफलताओं पर मौजूद; support को यही चाहिए |
http_status | 200 | transport का नतीजा |
result | valid, invalid, error, unknown | सामान्य किया गया नतीजा |
facts | फ़ैसले में इस्तेमाल हुए फ़ील्ड का छोटा JSON | सबूत, कम से कम |
decision | PASS, REVIEW, FAIL | आपने क्या तय किया |
reasons | ["NAME_DIFFERS"] | क्यों, कोड के रूप में |
policy_version | vendor-checks@7 | लागू नियम |
override_by, override_at, override_reason | user:asha@..., समय, पाठ | इंसानी बदलाव |
एक उदाहरण पंक्ति:
{
"id": "vr_01J9X2K8",
"subject_id": "vendor_1042",
"subject_kind": "GSTIN",
"subject_masked": "07*********Z1",
"subject_hash": "9b3f...e1",
"endpoint": "POST /v1/verify/gstin",
"environment": "production",
"requested_at": "2026-10-29T09:41:07Z",
"actor": "svc:onboarding-worker",
"reference_id": "SMV-20260927-9K21P4",
"request_id": null,
"http_status": 200,
"result": "valid",
"facts": { "registrationStatus": "Active", "embeddedPanMatches": true, "nameCompare": "COMPATIBLE" },
"decision": "PASS",
"reasons": [],
"policy_version": "vendor-checks@7"
}facts देखिए। उसमें वही तीन चीज़ें हैं जिन पर फ़ैसला सचमुच टिका था और कुछ और नहीं: status, GSTIN में बैठा PAN मेल खाया या नहीं, और नाम की तुलना का नतीजा। उसमें legal name, principal place of business या निदेशकों की सूची नहीं है। बाद के किसी सवाल को ज़्यादा चाहिए, तो reference_id और प्लेटफ़ॉर्म के अपने रिकॉर्ड रास्ता हैं, उनके रिटेंशन के भीतर।
एक पूरा उदाहरण: एक वेंडर, ऑनबोर्डिंग से भुगतान विवाद तक
एक काल्पनिक वेंडर "Sharma Traders" को रिकॉर्ड के सिलसिले में चलते देखिए, ताकि टुकड़े कैसे जुड़ते हैं यह दिखे।
मार्च में ऑनबोर्डिंग। onboarding worker वेंडर का PAN verify करता है। audit तालिका में एक पंक्ति जुड़ती है: subject_kind PAN, subject_masked AB******4F, keyed hash, endpoint POST /v1/verify/pan, reference_id SMV-...-8F42K7, result valid, facts में panStatus: VALID, holderTypeMatches: true और nameCompare: COMPATIBLE, decision REVIEW कारण NAME_COMPATIBLE_INITIALS_OR_MIDDLE के साथ, policy_version vendor-checks@7। कोई नाम नहीं, पिता का नाम नहीं, पूरा PAN नहीं। समीक्षक आशा PAN कार्ड की तस्वीर देखकर मंज़ूर करती है। पहली से जुड़ी दूसरी पंक्ति override_by: user:asha, समय और कारण "कार्ड की तस्वीर में आवेदन के बीच का नाम संक्षिप्त दिखता है" दर्ज करती है।
GSTIN और बैंक खाते की जाँचें उसी आकार की दो और पंक्तियाँ जोड़ती हैं। बैंक वाली पंक्ति खाते के आख़िरी चार अंक, पूरा IFSC, facts में utr, और verify किए PAN नाम से सामान्य किया nameCompare रखती है।
अगस्त में बदलाव। वेंडर ईमेल करता है कि उनके बैंक का ब्योरा बदल गया है। finance सिस्टम अनुरोध को नए खाते की तरह मानता है: नई bank account verification चलाता है, नए reference_id के साथ नई पंक्ति लिखता है, अगला भुगतान रोकता है, और वेंडर के जाने-पहचाने नंबर पर callback को कॉल करने वाले की id के साथ हाथ का क़दम बनाकर दर्ज करता है। पहले वाली पंक्ति को छुआ नहीं जाता।
नवंबर में विवाद। नए खाते में भुगतान गया और वेंडर कहता है कि पहुँचा नहीं। finance टीम वेंडर का रिकॉर्ड खोलती है और देखती है: अगस्त की bank verification की पंक्ति (खाते के आख़िरी चार अंक, result valid, nameCompare EXACT), रोक और दो अनुमोदकों के साथ उसकी रिहाई, और payments सिस्टम का भुगतान संदर्भ। वे बैंक को verification की पंक्ति का utr, जो penny-drop transfer की पहचान है, और खाते के आख़िरी चार अंक भेजते हैं। वे support के ज़रिए StampMitra से कहते हैं कि referenceId और समय से call का प्लेटफ़ॉर्म-पक्ष का रिकॉर्ड पक्का करे।
ध्यान दीजिए टीम ने क्या नहीं किया। उसने "फिर से जाँचने" के लिए verification दोबारा नहीं चलाई, जो अगस्त के फ़ैसले से असंबद्ध नया जवाब देती। उसने स्क्रीनशॉट के लिए ईमेल नहीं खँगाले। उसे logs में पूरी खाता संख्या की ज़रूरत नहीं पड़ी। रिकॉर्ड ने उन्हीं सवालों के जवाब दिए जिनके लिए वह बना था, और प्लेटफ़ॉर्म के अपने logs ने, अपने प्लान के रिटेंशन के भीतर, पुष्टि की कि call हुई थी।
क्या छिपाएँ, hash करें या कभी न रखें
| डेटा | audit रिकॉर्ड में | संचालन के logs में | टिप्पणी |
|---|---|---|---|
| PAN | छिपाकर; मिलान के लिए hash; पूरा मान तभी जब कोई नियम माँगे और एन्क्रिप्ट किए फ़ील्ड में | सिर्फ़ छिपाकर | गुप्त नहीं, पर निजी डेटा |
| GSTIN | छिपाकर; राज्य कोड और बैठे-PAN-के-मिलान का नतीजा तथ्य के रूप में | छिपाकर | कारोबारी डेटा, पर प्रोपराइटर के लिए व्यक्ति की पहचान |
| CIN | कंपनियों के लिए पूरा मान ठीक है, सार्वजनिक रजिस्ट्री डेटा के रूप में | पूरा या छिपाकर | कंपनी की सार्वजनिक पहचान |
| बैंक खाता संख्या | आख़िरी चार अंक; मिलान के लिए hash | सिर्फ़ आख़िरी चार | संवेदनशील वित्तीय डेटा; logs में पूरी संख्या कभी नहीं |
| IFSC | पूरा | पूरा | शाखा की पहचान, व्यक्ति की नहीं |
नाम (registeredName, nameAtBank, fatherName) | नाम की जगह तुलना का नतीजा और स्कोर रखिए | कभी नहीं | नाम रखना ही पड़े तो एन्क्रिप्ट करके |
| पता, principal place of business | आम तौर पर नहीं | कभी नहीं | तभी रखिए जब कोई नियम माँगे |
| निदेशक और DIN | सिर्फ़ यह तथ्य कि हस्ताक्षरकर्ता मिला | कभी नहीं | तीसरे पक्षों का निजी डेटा |
referenceId, requestId | हमेशा | हमेशा | ये प्लेटफ़ॉर्म के अपने रिकॉर्ड की कुंजियाँ हैं |
| API key और secrets | कभी नहीं | कभी नहीं | किसी log, टिकट या स्क्रीनशॉट में कभी नहीं |
| पूरे response या request बॉडी | नहीं | डिफ़ॉल्ट रूप से नहीं | अस्थायी, पहुँच-नियंत्रित डीबग capture अपवाद है |
| Aadhaar | लागू नहीं: StampMitra Aadhaar आधारित verification नहीं देता | इकट्ठा मत कीजिए | अपने सिस्टमों में नया Aadhaar डेटा मत बनाइए |
तालिका का पैटर्न हर पंक्ति में एक है: संकेतक, नतीजा या छिपा रूप रखिए। असली मान तभी रखिए जब कोई नियम माँगे, और तब भी एन्क्रिप्ट किए फ़ील्ड में जिसे कम लोग पढ़ें।
कोड में छिपाना और hash करना
import hashlib, hmac, os
def mask_pan(pan: str) -> str:
return f"{pan[:2]}******{pan[-2:]}" if pan and len(pan) == 10 else "[invalid]"
def mask_gstin(g: str) -> str:
return f"{g[:2]}*********{g[-2:]}" if g and len(g) == 15 else "[invalid]"
def mask_account(acct: str) -> str:
return "*" * (len(acct) - 4) + acct[-4:] if acct and len(acct) >= 9 else "[invalid]"
def subject_hash(kind: str, value: str) -> str:
salt = os.environ["AUDIT_HASH_SALT"].encode() # secret manager में रखिए, डेटाबेस में नहीं
return hmac.new(salt, f"{kind}:{value.upper().strip()}".encode(), hashlib.sha256).hexdigest()JavaScript में वही:
import crypto from "node:crypto";
export const maskPan = (pan) => (pan && pan.length === 10 ? `${pan.slice(0, 2)}******${pan.slice(-2)}` : "[invalid]");
export const maskAccount = (a) => (a && a.length >= 9 ? `${"*".repeat(a.length - 4)}${a.slice(-4)}` : "[invalid]");
export function subjectHash(kind, value, salt = process.env.AUDIT_HASH_SALT) {
return crypto.createHmac("sha256", salt).update(`${kind}:${value.toUpperCase().trim()}`).digest("hex");
}सिर्फ़ hash नहीं, गुप्त कुंजी के साथ HMAC इस्तेमाल कीजिए। PAN का सादा SHA-256 हर संभव PAN आज़माकर उलटा जा सकता है, क्योंकि संभावनाओं का दायरा छोटा है। डेटाबेस के बाहर रखी कुंजी वाला keyed hash नहीं उलटता।
StampMitra के request logs कहाँ फ़िट होते हैं
StampMitra आपके organisation के नाम से आपकी हर API call दर्ज करता है, और आप उन्हें API key से पढ़ सकते हैं। यह आपका स्वतंत्र सबूत है कि call हुई, जो ऑडिट के नवें सवाल का जवाब देता है।
GET /v1/logs पन्नों में items लौटाता है। हर एक में id, createdAt समय, actorType, pan.verify जैसा service code और metadata होता है। आप from, to, service और status (success या failure) से छान सकते हैं, और limit (200 तक) तथा nextCursor से पन्ने बदल सकते हैं।
curl -G "https://api-b2b.stampmitra.in/v1/logs" \
-H "Authorization: Bearer $STAMPMITRA_API_KEY" \
--data-urlencode "service=pan.verify" \
--data-urlencode "from=2026-10-29T00:00:00.000Z" \
--data-urlencode "to=2026-10-30T00:00:00.000Z" \
--data-urlencode "limit=200"ये क्या हैं और क्या नहीं, इस बारे में तीन बातें।
ये गतिविधि का log हैं, डेटा का भंडार नहीं। items service और समय बताते हैं, और मूल response बॉडी नहीं लौटाते। इसीलिए फ़ैसला और उसके तथ्य आपके अपने रिकॉर्ड में होने चाहिए।
इनका रिटेंशन आपके प्लान पर निर्भर है। प्रकाशित plan डेटा में log का रिटेंशन pay-as-you-go पर 30 दिन, Growth पर 90 दिन और Scale पर 365 दिन है, और sandbox प्लान की खिड़की छोटी है। आपकी audit अवधि लंबी हो तो जो चाहिए उसे नियमित अंतराल पर export कीजिए, और dashboard को संग्रह मत मानिए।
ये समय और service से जुड़े हैं, आपके विषय से नहीं। जब आपको साबित करना हो कि कोई ख़ास call हुई, तब आपके अपने रिकॉर्ड में सहेजा referenceId और logs पर समय-खिड़की की query साथ मिलकर सबूत देते हैं। एरर, retry और idempotency गाइड में एक पूरा उदाहरण है।
usage summary से मिलान
GET /v1/usage/summary मौजूदा बिलिंग अवधि के कुल लौटाता है: totalApiRequests, callsByService, callsByPeriod और callsByDay। इन्हें उसी अवधि और service के लिए आपके लिखे audit रिकॉर्डों की गिनती से मिलाइए। प्लेटफ़ॉर्म की ज़्यादा गिनती का मतलब बिना रिकॉर्ड की calls; कम का मतलब उन calls के रिकॉर्ड जो काम से पहले लौटा दी गईं। मासिक मिलान अपने आप में audit का नियंत्रण है। यह दिखाता है कि आपका रिकॉर्ड पूरा है।
रिटेंशन: क्या कितना रखें
कोई एक सही जवाब नहीं है, और यह गाइड कोई अंक नहीं देगी। जो कर सकती है वह यह कि ताक़तों को सामने रखे।
| ताक़त | किस ओर धकेलती है |
|---|---|
| KYC और लेन-देन के रिकॉर्ड के क्षेत्रीय नियम | तय अवधि तक रिकॉर्ड रखना, अक्सर संबंध ख़त्म होने के बाद वर्षों तक। आम नियम पाँच साल जैसी अवधियों की बात करते हैं, और मौजूदा अवधि तथा उसकी शुरुआत अपने नियामक या वकील से पक्की कीजिए |
| डेटा सुरक्षा के सिद्धांत (उद्देश्य की सीमा, भंडारण की सीमा) | निजी डेटा उतने ही समय रखना जितना उद्देश्य को चाहिए |
| विवाद और मुक़दमे की सीमाएँ | संभावित दावों की सीमा-अवधि तक सबूत रखना |
| लागत और उल्लंघन का जोखिम | कम रखना, क्योंकि हर रखी पहचान ऐसी चीज़ है जो लीक हो सकती है |
| पार्टनर और बैंक के अनुबंध | जो अनुबंध कहे |
सुलह इसमें है कि जो रखते हैं उसे अलग-अलग करें। न्यूनतम audit रिकॉर्ड लंबी अवधि के लिए रखिए, क्योंकि उसमें छिपे या hash किए विषय और सामान्य किए तथ्य हैं। कुछ भी भारी, जैसे एन्क्रिप्ट किए नाम या अपलोड किए दस्तावेज़, उतने कम समय के लिए रखिए जितना आपके नियम इजाज़त दें। संचालन के logs छोटे चक्र पर मिटाइए।
आपकी नीति में रिटेंशन की तालिका ऐसी हो सकती है, अपनी अवधियाँ भरकर।
| डेटा की श्रेणी | उदाहरण सामग्री | रिटेंशन (आप तय करें) | मिटाने का ट्रिगर |
|---|---|---|---|
| संचालन के logs | status code, समय, छिपा विषय | छोटा चक्र | समय |
| Audit रिकॉर्ड | ऊपर का न्यूनतम रिकॉर्ड | क्षेत्रीय नियम और नीति के अनुसार | रिटेंशन अवधि का अंत |
| एन्क्रिप्ट की पहचान का डेटा | नाम, जहाँ ज़रूरी हो पूरी पहचानें | जितनी कम अवधि आपके नियम दें | संबंध का अंत और अवधि |
| दस्तावेज़ | अपलोड किए प्रमाणपत्र | नीति के अनुसार | संबंध का अंत और अवधि |
| Export और backup | ऊपर की प्रतियाँ | स्रोत जितनी, और backup का जीवनचक्र | स्रोत जैसा |
StampMitra खुद क्या रखता है, इसके लिए इसका developer data retention और deletion schedule, developer privacy policy और data processing addendum पढ़िए। वे StampMitra का तरीक़ा बताते हैं, आपका तय नहीं करते।
रिटेंशन का job
from datetime import datetime, timedelta, timezone
RETENTION = { # आप और आपके compliance मालिक भरेंगे
"ops_log": timedelta(days=30),
"audit_record": timedelta(days=365 * 5),
"identity_blob": timedelta(days=365 * 5),
}
def sweep(db, now=None):
now = now or datetime.now(timezone.utc)
for table, keep in RETENTION.items():
cutoff = now - keep
n = db.delete_older_than(table, cutoff, respecting_legal_hold=True)
db.log_event("retention_sweep", table=table, cutoff=cutoff.isoformat(), deleted=n)ऊपर के अंक सिर्फ़ यह दिखाने वाले placeholder हैं कि संख्याएँ कहाँ जाती हैं। ये सिफ़ारिशें नहीं हैं। respecting_legal_hold देखिए: जब कोई विवाद या जाँच खुली हो, तब प्रभावित रिकॉर्डों के लिए सामान्य मिटाना रुकना चाहिए।
मिटाने के अनुरोध और वे रिकॉर्ड जो रखने ही हैं
कोई व्यक्ति आपसे अपना डेटा मिटाने को कह सकता है। कोई नियम आपसे verification रिकॉर्ड रखने को कह सकता है। दोनों एक साथ सच हो सकते हैं, और audit रिकॉर्ड की डिज़ाइन आपको हर हिस्से का सम्मान करने देती है।
समझदार बरताव यह है: जो रखना ज़रूरी नहीं उसे मिटाइए (भारी पहचान का डेटा, ऐसे दस्तावेज़ जो किसी नियम को नहीं चाहिए), जो रखना ज़रूरी है उसे रखिए (न्यूनतम audit रिकॉर्ड, छिपे और hash किए विषय के साथ), और व्यक्ति को बताइए कि आपने क्या रखा और क्यों। क्योंकि न्यूनतम रिकॉर्ड में पहले से असली मान की जगह छिपा विषय और keyed hash है, उसे रखना सबसे कम नुक़सान करता है। यह प्रक्रिया अपने वकील के साथ पहले से तय कीजिए, लिख लीजिए, और मिटाने के क़दमों को अफ़रा-तफ़री की जगह runbook बनाइए। सामान्य ढाँचे के लिए Digital Personal Data Protection Act, 2023 देखिए, और पक्का कीजिए कि वह आपके क्षेत्र के रिटेंशन नियमों के साथ कैसे चलता है।
सूचना और सहमति
रिकॉर्ड सिर्फ़ पिछला आधा है। अगला आधा लोगों को बताना है कि आप क्या इकट्ठा करते हैं और क्यों। जहाँ व्यक्ति PAN या बैंक खाता डालता है, वहाँ बताइए कि आप क्या जाँचेंगे, जाँच किसके साथ होगी, क्यों, और नतीजा कितने समय रखेंगे। वह वाक्य आपका उद्देश्य-कथन है, और आपके audit रिकॉर्ड के फ़ील्ड उससे मेल खाने चाहिए: अगर सूचना कहती है कि आप छिपी पहचान और नतीजा रखते हैं, तो चुपचाप नाम और पते भी मत रखिए।
पहुँच का नियंत्रण और एन्क्रिप्शन
audit का भंडार क़ीमती निशाना है, इसलिए उसे वैसा ही मानिए।
- न्यूनतम अधिकार। नामित छोटा समूह audit रिकॉर्ड पढ़ता है। इंजीनियर संचालन के logs पढ़ते हैं, audit का भंडार डिफ़ॉल्ट रूप से नहीं।
- पढ़ने को भी log कीजिए। दर्ज कीजिए कि किसने कौन-से audit रिकॉर्ड देखे, क्योंकि निजी डेटा तक पहुँच अपने आप में सबूत देने लायक़ चीज़ है।
- आराम और रास्ते में एन्क्रिप्शन। अपने प्लेटफ़ॉर्म का एन्क्रिप्शन इस्तेमाल कीजिए, और असली पहचानें या नाम रखने वाले हर फ़ील्ड के लिए अलग application-स्तर की कुंजी।
- कुंजियाँ अलग रखिए। hash का salt और फ़ील्ड-एन्क्रिप्शन की कुंजियाँ डेटाबेस से अलग, secret manager में।
- Backup। backup डेटा की संवेदनशीलता और रिटेंशन विरासत में पाते हैं। पक्का कीजिए कि स्रोत में मिटाना, तय अवधि के भीतर, backup में भी दिखे।
छेड़छाड़ का सबूत
audit रिकॉर्ड तब ज़्यादा विश्वसनीय होता है जब आप दिखा सकें कि किसी ने उसे बदला नहीं। दो सीधी आदतें मदद करती हैं।
Append-only भंडारण। पंक्तियाँ अपडेट मत कीजिए। सुधार और override पुरानी पंक्ति का हवाला देती नई पंक्तियाँ हैं। इसे डेटाबेस की अनुमतियों से लागू कीजिए: application की भूमिका के पास audit तालिका पर insert और select है, update या delete नहीं, और सिर्फ़ अलग retention भूमिका मिटा सकती है, अपने logging के साथ।
Hash chain। हर रिकॉर्ड में पिछले का hash शामिल रहता है, इसलिए बदली या हटाई पंक्ति chain तोड़ देती है।
import hashlib, json
def seal_record(record: dict, previous_hash: str | None) -> dict:
body = json.dumps(record, sort_keys=True, ensure_ascii=False)
h = hashlib.sha256(f"{previous_hash or ''}|{body}".encode()).hexdigest()
return {**record, "prev_hash": previous_hash, "hash": h}
def verify_chain(rows: list[dict]) -> dict:
prev = None
for row in rows:
rest = {k: v for k, v in row.items() if k not in ("hash", "prev_hash")}
if row["prev_hash"] != prev:
return {"ok": False, "broken_at": row["id"]}
body = json.dumps(rest, sort_keys=True, ensure_ascii=False)
if hashlib.sha256(f"{prev or ''}|{body}".encode()).hexdigest() != row["hash"]:
return {"ok": False, "broken_at": row["id"]}
prev = row["hash"]
return {"ok": True}chain पूरे डेटाबेस तक पहुँच वाले को सब कुछ दोबारा लिखने से नहीं रोकती, पर चुपचाप के बदलाव पकड़ में आने लायक़ बनाती है, और ताज़ा hash को डेटाबेस के बाहर कहीं (हस्ताक्षरित दैनिक नोट, अलग सिस्टम) प्रकाशित करने से दोबारा लिखना भी पकड़ में आने लायक़ हो जाता है। यह उस सबूत के लिए संतुलित नियंत्रण है जिसका आपको बचाव करना पड़ सकता है।
इंसानी फ़ैसले और override दर्ज करना
स्वचालित फ़ैसले आसान हिस्सा हैं। जो हिस्सा सवाल खींचता है वह तब है जब किसी इंसान ने दखल दिया। हर override के लिए दर्ज कीजिए: किसने, कब, स्वचालित फ़ैसला क्या था, इंसान ने क्या चुना, और कारण एक वाक्य के खुले पाठ में। इसे मूल से जुड़ी नई पंक्ति की तरह रखिए। कारण ज़रूरी कीजिए, क्योंकि बिना कारण का "मंज़ूर" वह रिकॉर्ड है जो ऑडिटर को सबसे कम पसंद है।
समीक्षक की पहचान स्थिर id के रूप में रखिए, सिर्फ़ दिखाने के नाम के रूप में नहीं, और वह भूमिका भी जिसमें उसने काम किया। किसी सीमा से ऊपर दूसरा अनुमोदक ज़रूरी हो तो दोनों रखिए। नीति बदले तो इतिहास दोबारा मत लिखिए: हर पंक्ति का policy_version पाठक को बताता है कि उस समय कौन-से नियम लागू थे।
विफलताएँ, अनजाने नतीजे और नकारात्मक नतीजे दर्ज करना
रिकॉर्ड को इस बारे में ईमानदार होना चाहिए कि क्या नहीं चला।
- नकारात्मक नतीजा (
valid: false) पूरी हुई lookup है। उसेresult: invalidके रूप में उसकेreferenceIdके साथ दर्ज कीजिए। वह एरर नहीं है। - एरर (400, 401, 402, 403, 429, 502)
result: errorके रूप मेंhttp_status,error.codeऔरrequest_idके साथ दर्ज होता है। लौटाई गई call का कोईreferenceIdनहीं होता। - अनजाना नतीजा (timeout)
result: unknownके रूप में दर्ज होता है, और logs जाँचने के बाद बाद मेंvalid,invalidयाerrorमें सुलझाया जाता है। इतिहास रखिए। जो ऑडिटरunknownके बाद समाधान देखता है, वह सीखता है कि आपने अस्पष्टता सँभाली। - Retry नई कोशिश है। उसे साझा
subject_idऔर उद्देश्य से पहली से जोड़कर रखिए, और पहले की पंक्ति कभी अधिलेखित मत कीजिए।
अपने स्टैक के किनारों पर redaction
सबसे अच्छी audit डिज़ाइन डीबगिंग की उस पंक्ति से बिगड़ जाती है जो request बॉडी छापती है। redaction वहाँ लगाइए जहाँ logs आपके कोड से निकलते हैं।
import logging, re
PAN = re.compile(r"\b[A-Z]{5}[0-9]{4}[A-Z]\b")
GSTIN = re.compile(r"\b[0-9]{2}[A-Z]{5}[0-9]{4}[A-Z][1-9A-Z]Z[0-9A-Z]\b")
KEY = re.compile(r"\bsk_(?:live|test)_[A-Za-z0-9_]+\b")
class RedactFilter(logging.Filter):
def filter(self, record):
msg = record.getMessage()
msg = KEY.sub("sk_***", msg)
msg = PAN.sub(lambda m: m.group(0)[:2] + "******" + m.group(0)[-2:], msg)
msg = GSTIN.sub(lambda m: m.group(0)[:2] + "*********" + m.group(0)[-2:], msg)
record.msg, record.args = msg, ()
return True
logging.getLogger().addFilter(RedactFilter())Node में pino का redact विकल्प वही काम करता है:
import pino from "pino";
export const logger = pino({
redact: {
paths: ["req.headers.authorization", "req.headers['x-api-key']", "*.pan", "*.gstin", "*.accountNumber", "*.name", "*.registeredName", "*.nameAtBank", "*.fatherName", "body", "response"],
censor: "[redacted]",
},
});उन दूसरी जगहों को भी जाँचिए जो चुपचाप डेटा पकड़ लेती हैं: error trackers जो request बॉडी जोड़ते हैं, APM उपकरण जो query strings दर्ज करते हैं, reverse proxy जो बॉडी log करते हैं, और ब्राउज़र के उपकरण जो फ़ॉर्म फ़ील्ड पकड़ते हैं। हर एक को वही फ़ील्ड छोड़ने या छिपाने के लिए सेट कीजिए। और key को कभी स्क्रीनशॉट, टिकट या चैट संदेश में मत जाने दीजिए।
ऑडिट के लिए सबूत तैयार करना
जब अनुरोध आए, तब आपको एक query चाहिए, कोई परियोजना नहीं।
-- एक वेंडर के सारे verification फ़ैसले, नए पहले, override के साथ
SELECT r.requested_at, r.subject_kind, r.subject_masked, r.result, r.decision, r.reasons,
r.policy_version, r.reference_id, o.override_by, o.override_reason
FROM verification_records r
LEFT JOIN verification_overrides o ON o.record_id = r.id
WHERE r.subject_id = :vendor_id
ORDER BY r.requested_at DESC;नतीजे के साथ एक पन्ने की व्याख्या रखिए कि रिकॉर्ड कैसे बना है: क्या रखा जाता है, क्या छिपाया जाता है, referenceId से प्लेटफ़ॉर्म के अपने logs से कैसे जुड़ता है, कितनी देर रखा जाता है और कौन पढ़ सकता है। वह पन्ना ऑडिटर के लिए उतना ही काम करता है जितना डेटा। किसी विवादित ख़ास call के लिए referenceId, समय और, विफल हुई हो तो, requestId दीजिए, और support से प्लेटफ़ॉर्म-पक्ष देखने को कहिए।
इस query का पूर्वाभ्यास ऑडिट आने से पहले कीजिए। किसी एक पुराने वेंडर को चुनिए, जिसे आपने खुद नहीं जोड़ा था, और किसी ऐसे साथी से कहिए जो इस सिस्टम पर नहीं चला हो कि वह सिर्फ़ इस query और उस एक पन्ने की व्याख्या से बताए कि उस वेंडर को क्यों मंज़ूर किया गया। जहाँ वह अटके, वहीं आपके रिकॉर्ड में कमी है: शायद नियम का संस्करण दर्ज नहीं, या override का कारण खाली है, या referenceId से जुड़ा कोई नतीजा खो गया है। ऐसे पूर्वाभ्यास साल में एक बार काफ़ी नहीं होते, इसलिए इसे अपने किसी नियमित चक्र (जैसे तिमाही की compliance समीक्षा) में रख दीजिए, और हर बार मिली कमियाँ उसी रिकॉर्ड-schema में सुधारकर सूचीबद्ध कीजिए, ताकि अगली बार वही कमी न लौटे।
schema की डिज़ाइन: index, partition और query
audit तालिका बिना सीमा के बढ़ती है, इसलिए कुछ डिज़ाइन चुनाव मायने रखते हैं।
जो query करते हैं उस पर index लगाइए। आम खोजें हैं subject_id से (एक वेंडर के बारे में सब कुछ), reference_id से (किसी platform call का रिकॉर्ड खोजना), subject_hash से (डुप्लिकेट और वेंडरों के बीच मेल) और requested_at से (अवधि की रिपोर्ट और रिटेंशन)। हर एक पर index लगाइए, और reference_id को एक environment के भीतर अद्वितीय रखिए।
समय से partition कीजिए। तालिका को महीने से partition कीजिए। तब रिटेंशन partition गिराना बन जाता है, जो तेज़ है और तालिका को फुलाता नहीं, और किसी अवधि की रिपोर्टें सिर्फ़ ज़रूरी partitions पढ़ती हैं।
facts को छोटा और संस्करणित रखिए। facts फ़ील्ड लचीला JSON दस्तावेज़ है, जो भटकाव न्योतता है। उसे schema का संस्करण दीजिए, लिखते समय validate कीजिए, और हर subject_kind के लिए कुंजियाँ दर्ज कीजिए। भविष्य के पाठक को अंदाज़ा नहीं लगाना पड़ना चाहिए कि 2026 में nameCompare का क्या मतलब था।
Environment अलग रखिए। हर पंक्ति में environment जोड़िए, और sandbox key से production रिकॉर्ड लिखने से मना कीजिए। सबूत के सिलसिले में sandbox का नतीजा ग़ायब रिकॉर्ड से बुरा है, क्योंकि वह असली दिखता है।
व्युत्पन्न पाठ मत रखिए। कारण कोड हैं, फ़ैसले enum हैं, नतीजे enum हैं। खुला पाठ सिर्फ़ override के कारणों में आता है। कोड गिने और query किए जा सकते हैं; वाक्य नहीं।
फ़ैसले के उसी transaction में लिखिए। अगर फ़ैसला और audit पंक्ति अलग हो सकते हैं, तो होंगे। दोनों साथ सहेजिए, या audit पंक्ति पहले लिखिए और फ़ैसले को उससे निकला मानिए।
रिकॉर्ड का मालिक कौन है
मालिक के बिना सिलसिला सड़ता है। भूमिकाओं के नाम तय कीजिए।
| भूमिका | ज़िम्मेदारी |
|---|---|
| Compliance मालिक | schema, रिटेंशन तालिका और मिटाने की प्रक्रिया मंज़ूर करता है; ऑडिटरों को जवाब देता है |
| Engineering मालिक | लिखने वाले कोड, redaction filters, मिलान job और रिटेंशन job को चलाता रखता है |
| सुरक्षा | पहुँच, एन्क्रिप्शन, कुंजियों का अलगाव और backup की समीक्षा करता है; घटना की प्रतिक्रिया का मालिक |
| डेटा सुरक्षा संपर्क | पहुँच और मिटाने के अनुरोध तथा privacy notice के शब्द सँभालता है |
| प्रक्रिया का कारोबारी मालिक | नीति के संस्करणों और उनके तहत लिए फ़ैसलों का मालिक |
इस व्यवस्था की साल में दो बार समीक्षा कीजिए। जाँचिए कि schema अब भी सूचना से मेल खाता है, रिटेंशन job चलता रहा है, मिलान सहनशीलता के भीतर है, और नामित समूह के बाहर किसी के पास पढ़ने की पहुँच नहीं।
किसी घटना के बाद
अगर लीक हो, तो रिकॉर्ड तय करता है कि वह कितना बुरा है। छिपे और hash किए विषयों के साथ audit भंडार का लीक पैटर्न और नतीजे खोलता है, असली पहचानें नहीं। application logs में असली पहचानों के साथ लीक हर उस व्यक्ति को खोलता है जिसे कभी verify किया गया। पहले से ये सवाल पूछिए: कौन-से भंडार में असली मान हैं, कौन उन्हें पढ़ सकता है, वे कितनी देर रखते हैं, और प्रभावित लोगों की सूची आप कितनी जल्दी बना सकते हैं। इनका जवाब देने वाला छोटा runbook ऐसी लंबी नीति से ज़्यादा काम का है जिसे किसी ने पढ़ा नहीं। StampMitra की घटना और उल्लंघन की सूचना की प्रक्रिया उसकी अपनी प्रक्रिया बताती है।
तैयारी की checklist
- संचालन के logs और audit रिकॉर्ड अलग हैं, अलग रिटेंशन और पहुँच के साथ।
- audit रिकॉर्ड न्यूनतम schema इस्तेमाल करता है,
referenceId, छिपे विषय, फ़ैसले, कारण और नीति के संस्करण के साथ। - पूरे PAN, खाता संख्या और response बॉडी संचालन के logs में नहीं हैं।
- मिलान के लिए hash keyed हैं (HMAC), कुंजी डेटाबेस के बाहर।
- audit पंक्तियाँ append-only हैं, override नई पंक्तियाँ हैं और हर एक पर कारण है।
- रिटेंशन की अवधियाँ लिखी हैं, compliance मालिक से मंज़ूर हैं और ऐसे job से लागू हैं जो legal hold का सम्मान करता है।
- मिटाने के अनुरोधों की दर्ज प्रक्रिया है जो जो मिटता है उसे जो रखना है उससे अलग करती है।
- audit रिकॉर्ड तक पहुँच सीमित और log की हुई है।
- redaction filters loggers, error trackers और proxies में लगे हैं।
- मासिक मिलान आपके रिकॉर्ड की गिनती को प्लेटफ़ॉर्म के usage summary से मिलाता है।
- एक रिपोर्ट query है जो एक विषय के लिए audit सबूत निकालती है।
- आपके प्लान के लिए प्लेटफ़ॉर्म के अपने log का रिटेंशन पता है, और उसके आगे जो चाहिए वह export होता है।
आम ग़लतियाँ
- एक ही log धारा को डीबगिंग की मदद और audit का सबूत, दोनों बना देना।
- पूरे request और response बॉडी को "अस्थायी रूप से" log करना और चालू छोड़ देना।
- पहचानों को ऐसे बिना कुंजी वाले hash से hash करना जो अनुमान लगाकर उलटा जा सकता है।
- "सब कुछ रखने" के लिए पूरा response रखना, और फिर ऐसे नाम, पते और निदेशक ब्योरे रखे बैठना जिनका किसी के पास उद्देश्य नहीं।
- फ़ैसला बदलने पर नई पंक्ति जोड़ने की जगह रिकॉर्ड को अधिलेखित करना।
- ऑडिटर को जवाब देने के लिए verification दोबारा चलाना, जो सबूत की जगह आज का जवाब रख देता है।
- यह मान लेना कि dashboard के request logs संग्रह हैं, जबकि रिटेंशन आपके प्लान पर निर्भर है।
- रिटेंशन की अवधि किसी ब्लॉग से, इस ब्लॉग से भी, उठाना, compliance के साथ तय करने की जगह।
- API key को log की पंक्ति, स्क्रीनशॉट या टिकट में जाने देना।
- sandbox रिकॉर्ड को production के सबूत से मिला देना, ताकि सैंपल नतीजा असली जाँच समझ लिया जाए।
आगे क्या करें
पहले न्यूनतम रिकॉर्ड का schema और छिपाने वाले helpers लिखिए, क्योंकि बाक़ी सब उन्हीं पर टँगा है। फिर अगली deployment से पहले redaction filters लगाइए। रिटेंशन की तालिका अपने compliance मालिक के साथ तय कीजिए। जिन जाँचों से ये रिकॉर्ड बनते हैं, उनके लिए वेंडर ऑनबोर्डिंग फ़्लो और KYC बनाम KYB पढ़िए। पुराने या विवादित नतीजों का क्या करें, इसके लिए API और सरकारी पोर्टल के नतीजों में फ़र्क पढ़िए। quickstart से sandbox key मिलती है। pay-as-you-go पर PAN की एक lookup ₹5 प्रति call है और bank account की जाँच ₹4 प्रति call, जो याद दिलाती है कि हर रिकॉर्ड एक बिल होने वाली call का है; pricing पेज देखिए। सवाल support को भेजिए।
API reference एक नज़र में
PAN
POST /v1/verify/panRequest parameters
| Field | Type | Description |
|---|---|---|
Authorizationrequired | header | Bearer <api-key> (e.g. sk_test_... in sandbox, sk_live_... in production). The x-api-key header is also accepted. |
panrequired | string | PAN, format ABCDE1234F. |
name | string | Name to match against records (max 256 chars). |
POST /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"
}POST /v1/verify/panPAN: ₹5 per successful call, pay-as-you-go (lower on Growth and Scale).
Bank Account
POST /v1/verify/bank-accountRequest parameters
| Field | Type | Description |
|---|---|---|
Authorizationrequired | header | Bearer <api-key> (e.g. sk_test_... in sandbox, sk_live_... in production). The x-api-key header is also accepted. |
accountNumberrequired | string | 9-18 digit numeric bank account number. |
ifscrequired | string | 11-character IFSC code, e.g. ICIC0001234. |
name | string | Beneficiary name to match. |
phone | string | Account holder's 10-digit Indian mobile number, when available; improves match confidence. |
POST /v1/verify/bank-account{
"referenceId": "SMV-20260927-3B71A0",
"valid": true,
"nameAtBank": "RAVI KUMAR",
"bankName": "ICICI Bank",
"utr": "017952100012345",
"city": "Mumbai",
"branch": "Andheri West",
"micr": "400229002",
"nameMatchScore": "100",
"nameMatchResult": "GOOD_MATCH",
"accountStatus": "ACCOUNT_IS_VALID",
"accountStatusCode": "1",
"ifscDetails": {
"bank": "ICICI Bank",
"ifsc": "ICIC0001234",
"micr": "400229002",
"address": "Andheri West, Mumbai",
"city": "Mumbai",
"state": "Maharashtra",
"branch": "Andheri West"
}
}POST /v1/verify/bank-accountBank Account: ₹4 per successful call, pay-as-you-go (lower on Growth and Scale).
अक्सर पूछे जाने वाले सवाल
verification call से मुझे क्या सहेजना चाहिए?
न्यूनतम audit रिकॉर्ड सहेजिए: छिपा विषय, मिलान के लिए keyed hash, endpoint, environment, समय, कर्ता, referenceId, फ़ैसले के तथ्य, फ़ैसला और कारण, नीति का संस्करण और कोई override किसने और क्यों। पूरे response की नक़ल से बचिए।
logs और audit रिकॉर्ड में क्या फ़र्क है?
संचालन के logs छोटी उम्र का डीबगिंग डेटा हैं, कम निजी डेटा और इंजीनियरों की चौड़ी पहुँच के साथ। audit रिकॉर्ड फ़ैसले का संरचित सबूत है, वर्षों रखा जाता है, append-only और नामित छोटे समूह के पढ़ने के लिए। दोनों अलग कामों के लिए इस्तेमाल कीजिए।
response रखे बिना बाद में call की पहचान कैसे करूँ?
StampMitra का referenceId, विफलता पर requestId, समय और endpoint सहेजिए। ये आपके रिकॉर्ड को प्लेटफ़ॉर्म के अपने request log से जोड़ते हैं, जिसे आप अपने प्लान के रिटेंशन के भीतर GET /v1/logs से खोज सकते हैं।
StampMitra मेरे request logs कितने समय रखता है?
यह आपके प्लान पर निर्भर है। प्रकाशित plan डेटा में pay-as-you-go पर 30 दिन, Growth पर 90 दिन और Scale पर 365 दिन हैं, और sandbox पर छोटी खिड़की। logs मूल response बॉडी नहीं लौटाते, इसलिए अपना audit रिकॉर्ड रखिए।
PAN और बैंक खाता संख्या कैसे छिपाएँ?
PAN के पहले दो और आख़िरी दो अक्षर दिखाइए, और खाता संख्या के सिर्फ़ आख़िरी चार अंक। मिलान के लिए डेटाबेस के बाहर रखी गुप्त कुंजी वाला keyed HMAC इस्तेमाल कीजिए, सादा hash नहीं, क्योंकि PAN का सादा hash अनुमान लगाकर उलटा जा सकता है।
verification रिकॉर्ड कितने समय रखने चाहिए?
यह नीति का फ़ैसला है। KYC के क्षेत्रीय नियम रिकॉर्ड वर्षों रखने को कह सकते हैं, जबकि डेटा सुरक्षा के सिद्धांत उसे मिटाने की ओर हैं जिसकी ज़रूरत नहीं। न्यूनतम छिपा रिकॉर्ड लंबी अवधि के लिए, भारी डेटा कम से कम अनुमत अवधि के लिए रखिए, और अवधियाँ अपने compliance मालिक से पक्की कीजिए।
कोई अपना डेटा मिटाने को कहे तो क्या करें?
जिसे रखना किसी नियम को ज़रूरी नहीं उसे मिटाइए, जो नियम माँगता है वह न्यूनतम audit रिकॉर्ड रखिए, और व्यक्ति को बताइए कि आपने क्या रखा और क्यों। छिपे विषय और keyed hash वाला रिकॉर्ड उस रखे जाने को सबसे कम नुक़सान वाला बना देता है।
क्या response का पंजीकृत नाम और निदेशकों का ब्योरा सहेजना चाहिए?
आम तौर पर नहीं। तुलना का नतीजा, जैसे COMPATIBLE या स्कोर, और यह तथ्य सहेजिए कि हस्ताक्षरकर्ता निदेशक से मिला। नाम रखना ही पड़े तो उसे एन्क्रिप्ट किए फ़ील्ड में रखिए जिसे कम लोग पढ़ें, उतनी ही कम अवधि के लिए जितनी आपके नियम दें।
audit रिकॉर्ड में छेड़छाड़ का सबूत कैसे बनाएँ?
तालिका को append-only रखिए, सुधार और override नई पंक्तियों के रूप में, delete का अधिकार अलग log की हुई भूमिका तक सीमित कीजिए, और hash chain पर विचार कीजिए जिसमें हर पंक्ति पिछली का hash रखे। ताज़ा hash डेटाबेस के बाहर प्रकाशित कीजिए ताकि पूरा दोबारा लिखना पकड़ में आए।
क्या ऑडिटर को जवाब देने के लिए verification दोबारा चला सकता हूँ?
नहीं। दोबारा चलाने पर आज का जवाब मिलता है, वह नहीं जिस पर आपने तब भरोसा किया था, और दूसरा referenceId बनता है। मूल फ़ैसले का सहेजा रिकॉर्ड निकालिए, और अगले कदम के लिए मौजूदा स्थिति चाहिए तभी दोबारा verify कीजिए।
स्रोत
GET /v1/logsऔरGET /v1/usage/summary, तथाreferenceIdऔर एरर के आकार के लिए StampMitra API reference डेटा, जैसा इस रिपॉज़िटरी में 2026-10-29 को है।- StampMitra का plan डेटा: प्लान के हिसाब से log का रिटेंशन (pay-as-you-go, Growth और Scale पर क्रमशः 30, 90 और 365 दिन), जैसा इस रिपॉज़िटरी के 2026-10-27 की तारीख़ वाले plan snapshot में है।
- डेटा के रिटेंशन और मिटाने, निजता, डेटा प्रोसेसिंग और घटना की सूचना पर StampMitra के कानूनी पन्ने, जैसे इस साइट पर 2026-10-29 को प्रकाशित हैं।
- Digital Personal Data Protection Act, 2023, India Code पर: https://www.indiacode.nic.in (सामान्य ढाँचा; यह आपके क्षेत्र के नियमों के साथ कैसे चलता है पक्का कीजिए, 2026)।
- भारतीय रिज़र्व बैंक, KYC पर Master Direction, और Prevention of Money-laundering Act, 2002 तथा उसके नियम, रिकॉर्ड रखरखाव पर: https://www.rbi.org.in और https://www.indiacode.nic.in (मौजूदा रिटेंशन अवधियाँ वहीं देखिए, 2026)।