{
  "info": {
    "_postman_id": "f3a9c2d1-6b4e-4f8a-9c7d-2e1b0a5d8f42",
    "name": "ASP Associates Verification APIs",
    "description": "## Overview\nProduction-grade Postman collection covering the five verticals of the ASP Associates identity & risk platform:\n\n1. **Identity Verification** \u2014 PAN, Aadhaar (OTP + Offline XML), Voter EPIC, Driving Licence (Sarathi 2.0), Passport\n2. **Workforce & BGV** \u2014 EPFO UAN Employment History v3 (member IDs, dual-employment / moonlighting detection)\n3. **Financial Intelligence** \u2014 NPCI IMPS Penny Drop, UPI VPA validation\n4. **Business & Tax** \u2014 GSTIN state decoding + GSTR-3B filing history\n5. **Mobility & Assets** \u2014 MoRTH Vahan 2.0 RC verification (hypothecation, fitness, insurance)\n\n## Authentication\nEvery endpoint requires the `x-api-key` header. The sandbox key ships as the collection variable `API_KEY` (`sandbox_key_asp_demo`). Swap in your production key via Environments before live traffic.\n\n## Conventions\n- A collection-level pre-request script auto-generates `REQUEST_ID` and `TIMESTAMP` for correlation on every call.\n- Consent flags (`consent`, `consent_text`) are mandatory on all KYC-touching endpoints per the DPDP Act, 2023.\n- Success envelope:\n```json\n{\n  \"success\": true,\n  \"request_id\": \"string\",\n  \"data\": {},\n  \"meta\": { \"latency_ms\": 0, \"credits_consumed\": 1 }\n}\n```\n- Error envelope:\n```json\n{\n  \"success\": false,\n  \"error\": { \"code\": \"string\", \"message\": \"string\", \"details\": {} }\n}\n```\n\n| HTTP | error.code | Meaning |\n|---|---|---|\n| 400 | INVALID_REQUEST | Payload failed schema / format validation |\n| 401 | UNAUTHORIZED | Missing or invalid `x-api-key` |\n| 402 | INSUFFICIENT_CREDITS | Verification wallet exhausted |\n| 409 | CONSENT_REQUIRED | Consent flags absent or false |\n| 422 | UPSTREAM_UNAVAILABLE | Registry (UIDAI / EPFO / Vahan / GSTN) degraded |\n| 429 | RATE_LIMITED | Throttled \u2014 honour the `Retry-After` header |\n\n## Operational Notes\n- The EPFO UAN endpoint may take up to **40 seconds**; configure client / proxy timeouts at 45s or higher.\n- Raw Aadhaar numbers are never persisted or echoed back \u2014 only masked references, hashes, and signed artifacts traverse responses.\n- Pre-request scripts act as zero-cost format gates so malformed payloads never consume an API credit.",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "event": [
    {
      "listen": "prerequest",
      "script": {
        "type": "text/javascript",
        "exec": [
          "// \u2500\u2500 Collection-wide instrumentation \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
          "// Fresh correlation id + ISO-8601 timestamp for every outbound call.",
          "pm.collectionVariables.set('REQUEST_ID', 'req_' + Date.now().toString(36) + '_' + Math.random().toString(36).slice(2, 8));",
          "pm.collectionVariables.set('TIMESTAMP', new Date().toISOString());",
          "",
          "// Fail fast on misconfiguration before burning a network round-trip.",
          "if (!pm.collectionVariables.get('BASE_URL')) {",
          "    throw new Error('Variable BASE_URL is unset. Expected default: https://www.aspassociates.in');",
          "}",
          "if (!pm.collectionVariables.get('API_KEY')) {",
          "    throw new Error('Variable API_KEY is unset. Sandbox default: sandbox_key_asp_demo');",
          "}"
        ]
      }
    }
  ],
  "variable": [
    {
      "key": "BASE_URL",
      "value": "https://www.aspassociates.in",
      "type": "string"
    },
    {
      "key": "API_KEY",
      "value": "sandbox_key_asp_demo",
      "type": "string"
    },
    {
      "key": "REQUEST_ID",
      "value": "",
      "type": "string"
    },
    {
      "key": "TIMESTAMP",
      "value": "",
      "type": "string"
    },
    {
      "key": "AADHAAR_TXN_ID",
      "value": "",
      "type": "string"
    },
    {
      "key": "GST_STATE_CODE",
      "value": "",
      "type": "string"
    },
    {
      "key": "GST_STATE_NAME",
      "value": "",
      "type": "string"
    },
    {
      "key": "VPA_HANDLE",
      "value": "",
      "type": "string"
    }
  ],
  "protocolProfileBehavior": {
    "disableBodyPruning": true
  },
  "item": [
    {
      "name": "1. Identity Verification",
      "description": "Government-ID verification suite. All endpoints require explicit DPDP-compliant consent flags and return a normalized `data` envelope with registry provenance (`source`) and a `checked_at` audit stamp.\n\nEndpoints:\n- **PAN** \u2014 format gate, ITD/NSDL operative status, Section 139AA Aadhaar seeding, fuzzy name match\n- **Aadhaar** \u2014 OTP trigger/verify flow + offline signed-XML (eKYC ZIP) flow\n- **Voter (EPIC)** \u2014 electoral-roll status, constituency, roll revision\n- **Driving Licence** \u2014 Sarathi 2.0 status + Class-of-Vehicle endorsements\n- **Passport** \u2014 file-number tracking through the CPV pipeline",
      "item": [
        {
          "name": "Verify PAN (Format + Operative + 139AA + Fuzzy Name)",
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// \u2500\u2500 Zero-cost PAN format gate \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
                  "// Reject malformed PANs locally so no API credit is consumed.",
                  "const body = JSON.parse(pm.request.body.raw);",
                  "const pan = String(body.pan_number || '').trim().toUpperCase();",
                  "",
                  "if (!/^[A-Z]{5}[0-9]{4}[A-Z]$/.test(pan)) {",
                  "    throw new Error('Invalid PAN format [' + pan + ']. Expected pattern ABCDE1234F (5 letters, 4 digits, 1 letter).');",
                  "}",
                  "",
                  "// 4th character encodes the holder class: P=Individual, C=Company, H=HUF,",
                  "// F=Firm, A=AOP, T=Trust, B=BOI, L=Local Authority, J=AJP, G=Government.",
                  "const holderTypeMap = {",
                  "    'P': 'Individual',",
                  "    'C': 'Company',",
                  "    'H': 'HUF',",
                  "    'F': 'Firm',",
                  "    'A': 'Association of Persons',",
                  "    'T': 'Trust',",
                  "    'B': 'Body of Individuals',",
                  "    'L': 'Local Authority',",
                  "    'J': 'Artificial Juridical Person',",
                  "    'G': 'Government'",
                  "};",
                  "const holderClass = holderTypeMap[pan.charAt(3)] || 'UNKNOWN';",
                  "pm.collectionVariables.set('PAN_HOLDER_CLASS', holderClass);",
                  "console.log('PAN holder class decoded from 4th char:', holderClass);"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('HTTP 200 OK', function () {",
                  "    pm.response.to.have.status(200);",
                  "});",
                  "",
                  "pm.test('Envelope: success=true with data object', function () {",
                  "    const json = pm.response.json();",
                  "    pm.expect(json.success).to.eql(true);",
                  "    pm.expect(json.data).to.be.an('object');",
                  "});",
                  "",
                  "pm.test('PAN operative status returned from ITD/NSDL source', function () {",
                  "    const d = pm.response.json().data;",
                  "    pm.expect(d.pan_status).to.be.oneOf(['OPERATIVE', 'INOPERATIVE', 'DEACTIVATED', 'NOT_FOUND']);",
                  "    pm.expect(d.source).to.be.a('string').and.not.empty;",
                  "});",
                  "",
                  "pm.test('Section 139AA Aadhaar-seeding status reported', function () {",
                  "    const d = pm.response.json().data;",
                  "    pm.expect(d).to.have.property('aadhaar_seeding_status');",
                  "    pm.expect(['LINKED', 'NOT_LINKED', 'NOT_APPLICABLE']).to.include(d.aadhaar_seeding_status);",
                  "    pm.expect(d.section_139aa_compliant).to.be.a('boolean');",
                  "});",
                  "",
                  "pm.test('Fuzzy name match score meets configured threshold', function () {",
                  "    const d = pm.response.json().data;",
                  "    pm.expect(d.name_match_score).to.be.a('number');",
                  "    pm.expect(d.name_match_score).to.be.at.least(d.fuzzy_match_threshold || 85);",
                  "});",
                  "",
                  "pm.test('Registry echo matches submitted PAN', function () {",
                  "    const body = JSON.parse(pm.request.body.raw);",
                  "    pm.expect(pm.response.json().data.pan_number).to.eql(body.pan_number.toUpperCase());",
                  "});",
                  "",
                  "pm.test('Latency under 10s', function () {",
                  "    pm.expect(pm.response.responseTime).to.be.below(10000);",
                  "});"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "x-api-key",
                "value": "{{API_KEY}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"request_id\": \"{{REQUEST_ID}}\",\n  \"timestamp\": \"{{TIMESTAMP}}\",\n  \"consent\": true,\n  \"consent_text\": \"I hereby provide my explicit consent to ASP Associates to fetch and process my KYC records from the Income Tax Department / NSDL e-Governance for verification purposes.\",\n  \"pan_number\": \"ABCDE1234F\",\n  \"full_name\": \"Shubham Sharma\",\n  \"date_of_birth\": \"1995-08-14\",\n  \"fuzzy_match_threshold\": 85\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{BASE_URL}}/api/v1/verify/pan",
              "host": [
                "{{BASE_URL}}"
              ],
              "path": [
                "api",
                "v1",
                "verify",
                "pan"
              ]
            },
            "description": "### PAN Verification\n\nPipeline:\n1. **Format gate** \u2014 `^[A-Z]{5}[0-9]{4}[A-Z]$` enforced locally in the pre-request script (zero-cost rejection).\n2. **Operative status** \u2014 live lookup against ITD provisional / NSDL e-Governance records.\n3. **Section 139AA** \u2014 Aadhaar-PAN seeding compliance flag (statutorily mandatory for individuals).\n4. **Fuzzy name match** \u2014 token-set ratio between submitted `full_name` and the registry name; threshold configurable per request.\n\n**Request schema**\n```json\n{\n  \"request_id\": \"string\",\n  \"timestamp\": \"ISO-8601\",\n  \"consent\": true,\n  \"consent_text\": \"string\",\n  \"pan_number\": \"ABCDE1234F\",\n  \"full_name\": \"string\",\n  \"date_of_birth\": \"YYYY-MM-DD\",\n  \"fuzzy_match_threshold\": 85\n}\n```\n\n**Key response fields**\n```json\n{\n  \"data\": {\n    \"pan_status\": \"OPERATIVE | INOPERATIVE | DEACTIVATED | NOT_FOUND\",\n    \"aadhaar_seeding_status\": \"LINKED | NOT_LINKED | NOT_APPLICABLE\",\n    \"section_139aa_compliant\": true,\n    \"name_match_score\": 96,\n    \"source\": \"NSDL_ETDS_ITD_PROVISIONAL\"\n  }\n}\n```"
          },
          "response": [
            {
              "name": "200 OK \u2014 Operative PAN, Aadhaar linked, name matched",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  },
                  {
                    "key": "x-api-key",
                    "value": "{{API_KEY}}"
                  }
                ],
                "url": {
                  "raw": "{{BASE_URL}}/api/v1/verify/pan",
                  "host": [
                    "{{BASE_URL}}"
                  ],
                  "path": [
                    "api",
                    "v1",
                    "verify",
                    "pan"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"request_id\": \"{{REQUEST_ID}}\",\n  \"timestamp\": \"{{TIMESTAMP}}\",\n  \"consent\": true,\n  \"consent_text\": \"I hereby provide my explicit consent to ASP Associates to fetch and process my KYC records from the Income Tax Department / NSDL e-Governance for verification purposes.\",\n  \"pan_number\": \"ABCDE1234F\",\n  \"full_name\": \"Shubham Sharma\",\n  \"date_of_birth\": \"1995-08-14\",\n  \"fuzzy_match_threshold\": 85\n}"
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"success\": true,\n  \"request_id\": \"req_m1abc2_x7k9pz\",\n  \"data\": {\n    \"pan_number\": \"ABCDE1234F\",\n    \"pan_status\": \"OPERATIVE\",\n    \"holder_category\": \"INDIVIDUAL\",\n    \"registered_name\": \"SHUBHAM SHARMA\",\n    \"name_match_score\": 96,\n    \"fuzzy_match_threshold\": 85,\n    \"aadhaar_seeding_status\": \"LINKED\",\n    \"section_139aa_compliant\": true,\n    \"source\": \"NSDL_ETDS_ITD_PROVISIONAL\",\n    \"checked_at\": \"2025-06-01T09:41:22Z\"\n  },\n  \"meta\": {\n    \"latency_ms\": 1840,\n    \"credits_consumed\": 1\n  }\n}"
            }
          ]
        },
        {
          "name": "Aadhaar eKYC (OTP & Offline XML)",
          "description": "Two flows against the same endpoint:\n\n1. **OTP flow (run in order)** \u2014 *Aadhaar OTP \u2014 Trigger* saves `{{AADHAAR_TXN_ID}}`; *Aadhaar OTP \u2014 Verify* exchanges the 6-digit OTP for demographics + signed artifacts.\n2. **Offline XML flow (standalone)** \u2014 verifies the Share-Code-protected eKYC ZIP generated from the mAadhaar app / UIDAI portal.\n\nRaw Aadhaar numbers are accepted transiently for routing only and never stored, logged, or echoed.",
          "item": [
            {
              "name": "Aadhaar OTP \u2014 Trigger",
              "event": [
                {
                  "listen": "prerequest",
                  "script": {
                    "type": "text/javascript",
                    "exec": [
                      "const body = JSON.parse(pm.request.body.raw);",
                      "const aadhaar = String(body.aadhaar_number || '').trim();",
                      "",
                      "// UIDAI rules: exactly 12 digits, cannot begin with 0 or 1.",
                      "// Full Verhoeff checksum validation runs server-side.",
                      "if (!/^[2-9][0-9]{11}$/.test(aadhaar)) {",
                      "    throw new Error('Invalid Aadhaar number. Must be 12 digits and cannot start with 0 or 1.');",
                      "}",
                      "",
                      "// Persist only a masked reference \u2014 never the raw number.",
                      "pm.collectionVariables.set('AADHAAR_MASKED', 'XXXX-XXXX-' + aadhaar.slice(-4));"
                    ]
                  }
                },
                {
                  "listen": "test",
                  "script": {
                    "type": "text/javascript",
                    "exec": [
                      "pm.test('HTTP 200 OK', function () {",
                      "    pm.response.to.have.status(200);",
                      "});",
                      "",
                      "pm.test('OTP dispatched and transaction handle issued', function () {",
                      "    const json = pm.response.json();",
                      "    pm.expect(json.success).to.eql(true);",
                      "    pm.expect(json.data.otp_dispatched).to.eql(true);",
                      "    pm.expect(json.data.transaction_id).to.be.a('string').and.not.empty;",
                      "    pm.collectionVariables.set('AADHAAR_TXN_ID', json.data.transaction_id);",
                      "});",
                      "",
                      "pm.test('Masked destination channel returned (mobile/email)', function () {",
                      "    const d = pm.response.json().data;",
                      "    pm.expect(d.masked_mobile_last4 || d.masked_email).to.exist;",
                      "});",
                      "",
                      "pm.test('OTP TTL and resend window communicated', function () {",
                      "    const d = pm.response.json().data;",
                      "    pm.expect(d.otp_ttl_seconds).to.be.a('number');",
                      "    pm.expect(d.resend_allowed_after_seconds).to.be.a('number');",
                      "});",
                      "",
                      "pm.test('Raw Aadhaar number never echoed in response', function () {",
                      "    pm.expect(pm.response.text()).to.not.contain(JSON.parse(pm.request.body.raw).aadhaar_number);",
                      "});"
                    ]
                  }
                }
              ],
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  },
                  {
                    "key": "x-api-key",
                    "value": "{{API_KEY}}"
                  },
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"request_id\": \"{{REQUEST_ID}}\",\n  \"timestamp\": \"{{TIMESTAMP}}\",\n  \"consent\": true,\n  \"consent_text\": \"I consent to UIDAI performing eKYC authentication against my Aadhaar using OTP-based verification.\",\n  \"flow\": \"OTP_TRIGGER\",\n  \"aadhaar_number\": \"234123412346\",\n  \"channel\": \"SMS\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{BASE_URL}}/api/v1/verify/aadhaar",
                  "host": [
                    "{{BASE_URL}}"
                  ],
                  "path": [
                    "api",
                    "v1",
                    "verify",
                    "aadhaar"
                  ]
                },
                "description": "### Aadhaar eKYC \u2014 Step 1: OTP Trigger\nInitiates UIDAI OTP authentication. Returns a `transaction_id` (auto-saved to `{{AADHAAR_TXN_ID}}` for the next step), the masked destination channel, and OTP TTL.\n\n**Request schema**\n```json\n{\n  \"flow\": \"OTP_TRIGGER\",\n  \"aadhaar_number\": \"12 digits, must not start with 0 or 1\",\n  \"channel\": \"SMS | EMAIL\"\n}\n```"
              },
              "response": [
                {
                  "name": "200 OK \u2014 OTP dispatched",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      },
                      {
                        "key": "x-api-key",
                        "value": "{{API_KEY}}"
                      }
                    ],
                    "url": {
                      "raw": "{{BASE_URL}}/api/v1/verify/aadhaar",
                      "host": [
                        "{{BASE_URL}}"
                      ],
                      "path": [
                        "api",
                        "v1",
                        "verify",
                        "aadhaar"
                      ]
                    },
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"request_id\": \"{{REQUEST_ID}}\",\n  \"timestamp\": \"{{TIMESTAMP}}\",\n  \"consent\": true,\n  \"consent_text\": \"I consent to UIDAI performing eKYC authentication against my Aadhaar using OTP-based verification.\",\n  \"flow\": \"OTP_TRIGGER\",\n  \"aadhaar_number\": \"234123412346\",\n  \"channel\": \"SMS\"\n}"
                    }
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"success\": true,\n  \"request_id\": \"req_k9d2ef_p3m8qt\",\n  \"data\": {\n    \"transaction_id\": \"txn_aadhaar_8f3d21c9\",\n    \"otp_dispatched\": true,\n    \"masked_mobile_last4\": \"4417\",\n    \"otp_ttl_seconds\": 180,\n    \"resend_allowed_after_seconds\": 30\n  },\n  \"meta\": {\n    \"latency_ms\": 1210,\n    \"credits_consumed\": 0\n  }\n}"
                }
              ]
            },
            {
              "name": "Aadhaar OTP \u2014 Verify",
              "event": [
                {
                  "listen": "prerequest",
                  "script": {
                    "type": "text/javascript",
                    "exec": [
                      "const body = JSON.parse(pm.request.body.raw);",
                      "",
                      "if (!/^[0-9]{6}$/.test(String(body.otp))) {",
                      "    throw new Error('OTP must be exactly 6 digits.');",
                      "}",
                      "",
                      "// Resolve the transaction handle: prefer an inline id, else fall back",
                      "// to the one saved by the OTP Trigger step.",
                      "const txn = (body.transaction_id && body.transaction_id.indexOf('{{') === -1)",
                      "    ? body.transaction_id",
                      "    : pm.collectionVariables.get('AADHAAR_TXN_ID');",
                      "",
                      "if (!txn) {",
                      "    throw new Error('No transaction_id available. Run the Aadhaar OTP \u2014 Trigger request first.');",
                      "}",
                      "pm.collectionVariables.set('AADHAAR_TXN_ID', txn);"
                    ]
                  }
                },
                {
                  "listen": "test",
                  "script": {
                    "type": "text/javascript",
                    "exec": [
                      "pm.test('HTTP 200 OK', function () {",
                      "    pm.response.to.have.status(200);",
                      "});",
                      "",
                      "pm.test('eKYC verified with full demographic payload', function () {",
                      "    const d = pm.response.json().data;",
                      "    pm.expect(d.kyc_status).to.eql('VERIFIED');",
                      "    pm.expect(d.demographics).to.have.property('name');",
                      "    pm.expect(d.demographics).to.have.property('dob');",
                      "    pm.expect(d.demographics).to.have.property('gender');",
                      "});",
                      "",
                      "pm.test('Address block present; no bare 12-digit Aadhaar leaked', function () {",
                      "    const demo = pm.response.json().data.demographics;",
                      "    pm.expect(demo.address).to.be.an('object');",
                      "    pm.expect(JSON.stringify(pm.response.json())).to.not.match(/\\b[0-9]{12}\\b/);",
                      "});",
                      "",
                      "pm.test('Signed XML and photo artifacts delivered as base64', function () {",
                      "    const artifacts = pm.response.json().data.artifacts;",
                      "    pm.expect(artifacts.signed_xml_base64).to.be.a('string').and.not.empty;",
                      "    pm.expect(artifacts.photo_base64).to.be.a('string').and.not.empty;",
                      "});",
                      "",
                      "pm.test('Authentication type recorded for audit trail', function () {",
                      "    pm.expect(pm.response.json().data.authentication_type).to.eql('OTP');",
                      "});"
                    ]
                  }
                }
              ],
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  },
                  {
                    "key": "x-api-key",
                    "value": "{{API_KEY}}"
                  },
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"request_id\": \"{{REQUEST_ID}}\",\n  \"timestamp\": \"{{TIMESTAMP}}\",\n  \"consent\": true,\n  \"consent_text\": \"I consent to UIDAI performing eKYC authentication against my Aadhaar using OTP-based verification.\",\n  \"flow\": \"OTP_VERIFY\",\n  \"transaction_id\": \"{{AADHAAR_TXN_ID}}\",\n  \"otp\": \"123456\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{BASE_URL}}/api/v1/verify/aadhaar",
                  "host": [
                    "{{BASE_URL}}"
                  ],
                  "path": [
                    "api",
                    "v1",
                    "verify",
                    "aadhaar"
                  ]
                },
                "description": "### Aadhaar eKYC \u2014 Step 2: OTP Verify\nExchanges the 6-digit OTP for a verified demographic payload plus signed artifacts. Demographics include name, DOB, gender, and full address; photo and digitally-signed XML arrive base64-encoded.\n\n**Request schema**\n```json\n{\n  \"flow\": \"OTP_VERIFY\",\n  \"transaction_id\": \"from Step 1\",\n  \"otp\": \"123456\"\n}\n```"
              },
              "response": [
                {
                  "name": "200 OK \u2014 eKYC verified",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      },
                      {
                        "key": "x-api-key",
                        "value": "{{API_KEY}}"
                      }
                    ],
                    "url": {
                      "raw": "{{BASE_URL}}/api/v1/verify/aadhaar",
                      "host": [
                        "{{BASE_URL}}"
                      ],
                      "path": [
                        "api",
                        "v1",
                        "verify",
                        "aadhaar"
                      ]
                    },
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"request_id\": \"{{REQUEST_ID}}\",\n  \"timestamp\": \"{{TIMESTAMP}}\",\n  \"consent\": true,\n  \"consent_text\": \"I consent to UIDAI performing eKYC authentication against my Aadhaar using OTP-based verification.\",\n  \"flow\": \"OTP_VERIFY\",\n  \"transaction_id\": \"{{AADHAAR_TXN_ID}}\",\n  \"otp\": \"123456\"\n}"
                    }
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"success\": true,\n  \"request_id\": \"req_q7w1mn_t2r6vd\",\n  \"data\": {\n    \"kyc_status\": \"VERIFIED\",\n    \"transaction_id\": \"txn_aadhaar_8f3d21c9\",\n    \"demographics\": {\n      \"name\": \"Shubham Sharma\",\n      \"dob\": \"1995-08-14\",\n      \"gender\": \"M\",\n      \"address\": {\n        \"care_of\": \"S/O R K Sharma\",\n        \"house\": \"B-14\",\n        \"street\": \"Model Town Phase 2\",\n        \"landmark\": \"Near City Park\",\n        \"locality\": \"Ashok Vihar\",\n        \"district\": \"North West Delhi\",\n        \"state\": \"DELHI\",\n        \"pincode\": \"110009\"\n      },\n      \"phone_last4\": \"4417\",\n      \"email_hash\": \"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\"\n    },\n    \"artifacts\": {\n      \"photo_base64\": \"/9j/4AAQSkZJRgABAQEAYABgAAD...\",\n      \"signed_xml_base64\": \"PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4...\"\n    },\n    \"authentication_type\": \"OTP\",\n    \"verified_at\": \"2025-06-01T09:44:03Z\"\n  },\n  \"meta\": {\n    \"latency_ms\": 2670,\n    \"credits_consumed\": 2\n  }\n}"
                }
              ]
            },
            {
              "name": "Aadhaar Offline XML (eKYC ZIP)",
              "event": [
                {
                  "listen": "prerequest",
                  "script": {
                    "type": "text/javascript",
                    "exec": [
                      "const body = JSON.parse(pm.request.body.raw);",
                      "",
                      "if (!body.file_base64 || String(body.file_base64).length < 512) {",
                      "    throw new Error('file_base64 must contain the base64-encoded offline eKYC ZIP (Share-Code protected).');",
                      "}",
                      "",
                      "if (!/^[0-9]{4}$/.test(String(body.share_code))) {",
                      "    throw new Error('share_code must be the exact 4-digit code chosen when downloading the XML from UIDAI.');",
                      "}"
                    ]
                  }
                },
                {
                  "listen": "test",
                  "script": {
                    "type": "text/javascript",
                    "exec": [
                      "pm.test('HTTP 200 OK', function () {",
                      "    pm.response.to.have.status(200);",
                      "});",
                      "",
                      "pm.test('ZIP integrity and Share-Code decryption succeeded', function () {",
                      "    const json = pm.response.json();",
                      "    pm.expect(json.success).to.eql(true);",
                      "    pm.expect(json.data.xml_integrity).to.eql('PASS');",
                      "});",
                      "",
                      "pm.test('UIDAI reference ID in NNNN-YYYY-NNNN format', function () {",
                      "    pm.expect(pm.response.json().data.reference_id).to.match(/^[0-9]{4}-[0-9]{4}-[0-9]{4}$/);",
                      "});",
                      "",
                      "pm.test('Demographics extracted from signed XML', function () {",
                      "    const d = pm.response.json().data;",
                      "    pm.expect(d.demographics.name).to.exist;",
                      "    pm.expect(d.demographics.dob).to.exist;",
                      "    pm.expect(d.demographics.gender).to.exist;",
                      "});",
                      "",
                      "pm.test('SHA-256 digest of verified XML recorded', function () {",
                      "    pm.expect(pm.response.json().data.digest_sha256).to.match(/^[a-f0-9]{64}$/);",
                      "});"
                    ]
                  }
                }
              ],
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  },
                  {
                    "key": "x-api-key",
                    "value": "{{API_KEY}}"
                  },
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"request_id\": \"{{REQUEST_ID}}\",\n  \"timestamp\": \"{{TIMESTAMP}}\",\n  \"consent\": true,\n  \"consent_text\": \"I consent to ASP Associates processing my UIDAI offline eKYC document for identity verification.\",\n  \"flow\": \"XML_OFFLINE\",\n  \"file_base64\": \"UEsDBBQAAAAIAKZ2c1hY...truncated-base64-offline-ekyc-zip...\",\n  \"share_code\": \"1234\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{BASE_URL}}/api/v1/verify/aadhaar",
                  "host": [
                    "{{BASE_URL}}"
                  ],
                  "path": [
                    "api",
                    "v1",
                    "verify",
                    "aadhaar"
                  ]
                },
                "description": "### Aadhaar Offline eKYC \u2014 Signed XML (ZIP)\nVerifies the password-protected offline eKYC ZIP generated from the mAadhaar app / UIDAI portal. Supply the exact 4-digit **Share Code** used at download time; the service decrypts, validates the signed-XML digest, and extracts demographics plus the UIDAI reference ID (last-4 of Aadhaar + timestamp).\n\n**Request schema**\n```json\n{\n  \"flow\": \"XML_OFFLINE\",\n  \"file_base64\": \"base64(ZIP)\",\n  \"share_code\": \"1234\"\n}\n```"
              },
              "response": [
                {
                  "name": "200 OK \u2014 XML integrity PASS",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      },
                      {
                        "key": "x-api-key",
                        "value": "{{API_KEY}}"
                      }
                    ],
                    "url": {
                      "raw": "{{BASE_URL}}/api/v1/verify/aadhaar",
                      "host": [
                        "{{BASE_URL}}"
                      ],
                      "path": [
                        "api",
                        "v1",
                        "verify",
                        "aadhaar"
                      ]
                    },
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"request_id\": \"{{REQUEST_ID}}\",\n  \"timestamp\": \"{{TIMESTAMP}}\",\n  \"consent\": true,\n  \"consent_text\": \"I consent to ASP Associates processing my UIDAI offline eKYC document for identity verification.\",\n  \"flow\": \"XML_OFFLINE\",\n  \"file_base64\": \"UEsDBBQAAAAIAKZ2c1hY...truncated-base64-offline-ekyc-zip...\",\n  \"share_code\": \"1234\"\n}"
                    }
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"success\": true,\n  \"request_id\": \"req_z4x8pl_n6w3ke\",\n  \"data\": {\n    \"xml_integrity\": \"PASS\",\n    \"reference_id\": \"2346-2025-8841\",\n    \"demographics\": {\n      \"name\": \"Shubham Sharma\",\n      \"dob\": \"14-08-1995\",\n      \"gender\": \"M\",\n      \"address_hash_present\": true\n    },\n    \"digest_sha256\": \"9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08\",\n    \"verified_at\": \"2025-06-01T09:47:31Z\"\n  },\n  \"meta\": {\n    \"latency_ms\": 1980,\n    \"credits_consumed\": 1\n  }\n}"
                }
              ]
            }
          ]
        },
        {
          "name": "Verify Voter ID (EPIC)",
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const body = JSON.parse(pm.request.body.raw);",
                  "const epic = String(body.epic_number || '').trim().toUpperCase();",
                  "",
                  "// EPIC format: 3 alphabetic characters + 7 digits (e.g., ABC1234567).",
                  "if (!/^[A-Z]{3}[0-9]{7}$/.test(epic)) {",
                  "    throw new Error('Invalid EPIC format [' + epic + ']. Expected 3 letters followed by 7 digits (e.g., ABC1234567).');",
                  "}",
                  "",
                  "pm.collectionVariables.set('EPIC_NORMALIZED', epic);"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('HTTP 200 OK', function () {",
                  "    pm.response.to.have.status(200);",
                  "});",
                  "",
                  "pm.test('Elector record found with enumerated status', function () {",
                  "    const d = pm.response.json().data;",
                  "    pm.expect(d.voter_status).to.be.oneOf(['ACTIVE', 'SUSPENDED', 'DUPLICATE_EPIC', 'NOT_FOUND']);",
                  "});",
                  "",
                  "pm.test('Electoral roll metadata present', function () {",
                  "    const d = pm.response.json().data;",
                  "    pm.expect(d.state_code).to.be.a('string').and.not.empty;",
                  "    pm.expect(d.constituency).to.exist;",
                  "    pm.expect(d.roll_revision_year).to.be.a('number');",
                  "});",
                  "",
                  "pm.test('Name similarity against electoral roll computed', function () {",
                  "    pm.expect(pm.response.json().data.name_match_score).to.be.at.least(80);",
                  "});",
                  "",
                  "pm.test('Relative name captured (BGV co-reference signal)', function () {",
                  "    pm.expect(pm.response.json().data).to.have.property('relative_name');",
                  "});"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "x-api-key",
                "value": "{{API_KEY}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"request_id\": \"{{REQUEST_ID}}\",\n  \"timestamp\": \"{{TIMESTAMP}}\",\n  \"consent\": true,\n  \"consent_text\": \"I hereby consent to ASP Associates verifying my Voter ID details against the electoral roll maintained by the Election Commission of India.\",\n  \"epic_number\": \"ABC1234567\",\n  \"full_name\": \"Shubham Sharma\",\n  \"state_code\": \"DL\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{BASE_URL}}/api/v1/verify/voter",
              "host": [
                "{{BASE_URL}}"
              ],
              "path": [
                "api",
                "v1",
                "verify",
                "voter"
              ]
            },
            "description": "### Voter ID (EPIC) Verification\nChecks the Electors Photo Identity Card against State Election Commission rolls: elector status, constituency, latest roll revision year, relative name, and fuzzy name score.\n\n**Format**: 3 alpha + 7 digits (e.g., `ABC1234567`).\n\n**Request schema**\n```json\n{\n  \"epic_number\": \"ABC1234567\",\n  \"full_name\": \"string\",\n  \"state_code\": \"DL\"\n}\n```"
          },
          "response": [
            {
              "name": "200 OK \u2014 Active elector found",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  },
                  {
                    "key": "x-api-key",
                    "value": "{{API_KEY}}"
                  }
                ],
                "url": {
                  "raw": "{{BASE_URL}}/api/v1/verify/voter",
                  "host": [
                    "{{BASE_URL}}"
                  ],
                  "path": [
                    "api",
                    "v1",
                    "verify",
                    "voter"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"request_id\": \"{{REQUEST_ID}}\",\n  \"timestamp\": \"{{TIMESTAMP}}\",\n  \"consent\": true,\n  \"consent_text\": \"I hereby consent to ASP Associates verifying my Voter ID details against the electoral roll maintained by the Election Commission of India.\",\n  \"epic_number\": \"ABC1234567\",\n  \"full_name\": \"Shubham Sharma\",\n  \"state_code\": \"DL\"\n}"
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"success\": true,\n  \"request_id\": \"req_b2n7vc_j4h9sd\",\n  \"data\": {\n    \"epic_number\": \"ABC1234567\",\n    \"voter_status\": \"ACTIVE\",\n    \"registered_name\": \"SHUBHAM SHARMA\",\n    \"name_match_score\": 94,\n    \"relative_name\": \"R K SHARMA\",\n    \"state_code\": \"DL\",\n    \"constituency\": \"Model Town (Assembly)\",\n    \"roll_revision_year\": 2024,\n    \"age_band\": \"25-29\",\n    \"checked_at\": \"2025-06-01T09:51:10Z\"\n  },\n  \"meta\": {\n    \"latency_ms\": 1520,\n    \"credits_consumed\": 1\n  }\n}"
            }
          ]
        },
        {
          "name": "Verify Driving Licence (Sarathi 2.0)",
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const body = JSON.parse(pm.request.body.raw);",
                  "const dl = String(body.dl_number || '').trim().toUpperCase().replace(/[^A-Z0-9]/g, '');",
                  "",
                  "// Sarathi DL 2.0 pattern: SS + RTO code + issue-year + serial,",
                  "// e.g., DL1420190005678 -> DL / 14 / 2019 / 0005678.",
                  "if (!/^[A-Z]{2}[0-9]{2}(19|20)[0-9]{7,9}$/.test(dl)) {",
                  "    throw new Error('DL does not match the Sarathi 2.0 pattern (e.g., DL1420190005678). Received: ' + dl);",
                  "}",
                  "",
                  "pm.collectionVariables.set('DL_NORMALIZED', dl);"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('HTTP 200 OK', function () {",
                  "    pm.response.to.have.status(200);",
                  "});",
                  "",
                  "pm.test('DL status enumerated per Sarathi 2.0', function () {",
                  "    const d = pm.response.json().data;",
                  "    pm.expect(d.dl_status).to.be.oneOf(['VALID', 'EXPIRED', 'SUSPENDED', 'CANCELLED', 'NOT_FOUND']);",
                  "});",
                  "",
                  "pm.test('Vehicle classes returned and cover requested classes', function () {",
                  "    const d = pm.response.json().data;",
                  "    pm.expect(d.vehicle_classes).to.be.an('array').that.is.not.empty;",
                  "    const classCodes = d.vehicle_classes.map(function (c) { return c.class_code; });",
                  "    pm.expect(classCodes).to.include('LMV');",
                  "});",
                  "",
                  "pm.test('Per-class COV validity windows present', function () {",
                  "    const first = pm.response.json().data.vehicle_classes[0];",
                  "    pm.expect(first).to.have.property('cov_valid_from');",
                  "    pm.expect(first).to.have.property('cov_valid_to');",
                  "});",
                  "",
                  "pm.test('Overall licence validity window parsed', function () {",
                  "    const d = pm.response.json().data;",
                  "    pm.expect(d.valid_from).to.exist;",
                  "    pm.expect(d.valid_to).to.exist;",
                  "});",
                  "",
                  "pm.test('Issuing RTO identified', function () {",
                  "    pm.expect(pm.response.json().data.issuing_rto).to.be.a('string').and.not.empty;",
                  "});"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "x-api-key",
                "value": "{{API_KEY}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"request_id\": \"{{REQUEST_ID}}\",\n  \"timestamp\": \"{{TIMESTAMP}}\",\n  \"consent\": true,\n  \"consent_text\": \"I hereby consent to ASP Associates verifying my Driving Licence details against the Ministry of Road Transport and Highways (Sarathi) records.\",\n  \"dl_number\": \"DL1420190005678\",\n  \"date_of_birth\": \"1995-08-14\",\n  \"expected_vehicle_classes\": [\n    \"LMV\",\n    \"MCWG\"\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{BASE_URL}}/api/v1/verify/driving-license",
              "host": [
                "{{BASE_URL}}"
              ],
              "path": [
                "api",
                "v1",
                "verify",
                "driving-license"
              ]
            },
            "description": "### Driving Licence \u2014 Sarathi 2.0\nResolves DL status, Class-of-Vehicle endorsements (LMV, MCWG, MCXG, HMV, HGMV, HPMV, TRV, etc.) with per-class validity windows, issuing RTO, blood group, and overall licence validity.\n\n**Format**: `SS RR YYYY NNNNNNN(N)` \u2014 e.g., `DL1420190005678`.\n\n**Request schema**\n```json\n{\n  \"dl_number\": \"DL1420190005678\",\n  \"date_of_birth\": \"YYYY-MM-DD\",\n  \"expected_vehicle_classes\": [\"LMV\", \"MCWG\"]\n}\n```"
          },
          "response": [
            {
              "name": "200 OK \u2014 Valid DL with LMV + MCWG",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  },
                  {
                    "key": "x-api-key",
                    "value": "{{API_KEY}}"
                  }
                ],
                "url": {
                  "raw": "{{BASE_URL}}/api/v1/verify/driving-license",
                  "host": [
                    "{{BASE_URL}}"
                  ],
                  "path": [
                    "api",
                    "v1",
                    "verify",
                    "driving-license"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"request_id\": \"{{REQUEST_ID}}\",\n  \"timestamp\": \"{{TIMESTAMP}}\",\n  \"consent\": true,\n  \"consent_text\": \"I hereby consent to ASP Associates verifying my Driving Licence details against the Ministry of Road Transport and Highways (Sarathi) records.\",\n  \"dl_number\": \"DL1420190005678\",\n  \"date_of_birth\": \"1995-08-14\",\n  \"expected_vehicle_classes\": [\n    \"LMV\",\n    \"MCWG\"\n  ]\n}"
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"success\": true,\n  \"request_id\": \"req_c5t2gh_w8y1rn\",\n  \"data\": {\n    \"dl_number\": \"DL1420190005678\",\n    \"dl_status\": \"VALID\",\n    \"holder_name\": \"SHUBHAM SHARMA\",\n    \"date_of_birth\": \"1995-08-14\",\n    \"vehicle_classes\": [\n      {\n        \"class_code\": \"LMV\",\n        \"class_description\": \"Light Motor Vehicle\",\n        \"cov_valid_from\": \"2019-05-02\",\n        \"cov_valid_to\": \"2041-05-01\"\n      },\n      {\n        \"class_code\": \"MCWG\",\n        \"class_description\": \"Motorcycle With Gear\",\n        \"cov_valid_from\": \"2019-05-02\",\n        \"cov_valid_to\": \"2041-05-01\"\n      }\n    ],\n    \"valid_from\": \"2019-05-02\",\n    \"valid_to\": \"2041-05-01\",\n    \"issuing_rto\": \"DL-14 Delhi (Rohini)\",\n    \"blood_group\": \"O+\",\n    \"source\": \"SARTHI_DL_2_0\",\n    \"checked_at\": \"2025-06-01T09:54:47Z\"\n  },\n  \"meta\": {\n    \"latency_ms\": 2110,\n    \"credits_consumed\": 1\n  }\n}"
            }
          ]
        },
        {
          "name": "Verify Passport File Status",
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const body = JSON.parse(pm.request.body.raw);",
                  "const fileNo = String(body.passport_file_number || '').trim().toUpperCase();",
                  "",
                  "// File number: letter followed by 7-14 alphanumerics (e.g., A01234567).",
                  "if (!/^[A-Z]{1}[0-9]{7,14}$/.test(fileNo)) {",
                  "    throw new Error('Passport file number must start with a letter followed by 7-14 alphanumeric characters (e.g., A01234567).');",
                  "}",
                  "",
                  "// Booklet number: letter + 7 digits (e.g., M1234567). Optional but validated if present.",
                  "if (body.passport_number && !/^[A-Z]{1}[0-9]{7}$/.test(String(body.passport_number).toUpperCase())) {",
                  "    throw new Error('Passport booklet number must match the M1234567 pattern (letter + 7 digits).');",
                  "}"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('HTTP 200 OK', function () {",
                  "    pm.response.to.have.status(200);",
                  "});",
                  "",
                  "pm.test('Application/file status resolved', function () {",
                  "    const d = pm.response.json().data;",
                  "    pm.expect(d.passport_status).to.be.oneOf(['ISSUED', 'UNDER_PROCESS', 'DISPATCHED', 'POLICY_VERIFICATION_PENDING', 'NOT_FOUND']);",
                  "});",
                  "",
                  "pm.test('File number echoed back matches request', function () {",
                  "    const body = JSON.parse(pm.request.body.raw);",
                  "    pm.expect(pm.response.json().data.file_number.toUpperCase()).to.eql(body.passport_file_number.toUpperCase());",
                  "});",
                  "",
                  "pm.test('Issue/expiry dates and office present when ISSUED', function () {",
                  "    const d = pm.response.json().data;",
                  "    if (d.passport_status === 'ISSUED') {",
                  "        pm.expect(d.issue_date).to.exist;",
                  "        pm.expect(d.expiry_date).to.exist;",
                  "        pm.expect(d.issuing_office).to.exist;",
                  "    }",
                  "});",
                  "",
                  "pm.test('Booklet type recorded when issued', function () {",
                  "    const d = pm.response.json().data;",
                  "    if (d.passport_status === 'ISSUED') {",
                  "        pm.expect(d.booklet_type).to.be.oneOf(['30_PAGES', '36_PAGES', '60_PAGES']);",
                  "    }",
                  "});"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "x-api-key",
                "value": "{{API_KEY}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"request_id\": \"{{REQUEST_ID}}\",\n  \"timestamp\": \"{{TIMESTAMP}}\",\n  \"consent\": true,\n  \"consent_text\": \"I hereby consent to ASP Associates verifying my passport application/file status with the Consular, Passport and Visa Division.\",\n  \"passport_file_number\": \"A01234567\",\n  \"passport_number\": \"M1234567\",\n  \"date_of_birth\": \"1995-08-14\",\n  \"given_name\": \"Shubham Sharma\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{BASE_URL}}/api/v1/verify/passport",
              "host": [
                "{{BASE_URL}}"
              ],
              "path": [
                "api",
                "v1",
                "verify",
                "passport"
              ]
            },
            "description": "### Passport File Status\nTracks a passport application/file through the Consular, Passport & Visa (CPV) Division pipeline: `UNDER_PROCESS` \u2192 `POLICY_VERIFICATION_PENDING` \u2192 `DISPATCHED` \u2192 `ISSUED`, with booklet details upon issuance.\n\n**Formats**: file number `A01234567` (letter + 7\u201314 alphanumerics); booklet `M1234567` (letter + 7 digits).\n\n**Request schema**\n```json\n{\n  \"passport_file_number\": \"A01234567\",\n  \"passport_number\": \"M1234567\",\n  \"date_of_birth\": \"YYYY-MM-DD\",\n  \"given_name\": \"string\"\n}\n```"
          },
          "response": [
            {
              "name": "200 OK \u2014 Passport issued",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  },
                  {
                    "key": "x-api-key",
                    "value": "{{API_KEY}}"
                  }
                ],
                "url": {
                  "raw": "{{BASE_URL}}/api/v1/verify/passport",
                  "host": [
                    "{{BASE_URL}}"
                  ],
                  "path": [
                    "api",
                    "v1",
                    "verify",
                    "passport"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"request_id\": \"{{REQUEST_ID}}\",\n  \"timestamp\": \"{{TIMESTAMP}}\",\n  \"consent\": true,\n  \"consent_text\": \"I hereby consent to ASP Associates verifying my passport application/file status with the Consular, Passport and Visa Division.\",\n  \"passport_file_number\": \"A01234567\",\n  \"passport_number\": \"M1234567\",\n  \"date_of_birth\": \"1995-08-14\",\n  \"given_name\": \"Shubham Sharma\"\n}"
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"success\": true,\n  \"request_id\": \"req_d9m3jk_v5u7qb\",\n  \"data\": {\n    \"file_number\": \"A01234567\",\n    \"passport_number\": \"M1234567\",\n    \"passport_status\": \"ISSUED\",\n    \"applicant_name\": \"SHUBHAM SHARMA\",\n    \"issue_date\": \"2019-11-20\",\n    \"expiry_date\": \"2029-11-19\",\n    \"issuing_office\": \"CPV DELHI\",\n    \"booklet_type\": \"36_PAGES\",\n    \"checked_at\": \"2025-06-01T09:58:12Z\"\n  },\n  \"meta\": {\n    \"latency_ms\": 1740,\n    \"credits_consumed\": 1\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "2. Workforce & BGV",
      "description": "Background-verification vertical built on the EPFO gateway. The flagship UAN Employment History v3 endpoint reconstructs a candidate's formal employment trail and derives dual-employment (moonlighting) signals from overlapping active tenures.\n\nTimeout guidance: the EPFO gateway is batch-oriented \u2014 budget **40 seconds** and configure client timeouts at 45s+.",
      "item": [
        {
          "name": "UAN Employment History v3 (EPFO)",
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const body = JSON.parse(pm.request.body.raw);",
                  "const uan = String(body.uan || '').trim();",
                  "",
                  "if (!/^[0-9]{12}$/.test(uan)) {",
                  "    throw new Error('UAN must be exactly 12 digits.');",
                  "}",
                  "",
                  "// Warn operators about the EPFO gateway latency profile.",
                  "console.log('NOTE: EPFO gateway calls can take up to 40s. Ensure client/proxy timeout >= 45000ms.');",
                  "pm.collectionVariables.set('UAN_LAST4', uan.slice(-4));"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('HTTP 200 OK', function () {",
                  "    pm.response.to.have.status(200);",
                  "});",
                  "",
                  "pm.test('Gateway responded within the 40s SLA', function () {",
                  "    pm.expect(pm.response.responseTime).to.be.below(40000);",
                  "});",
                  "",
                  "pm.test('Employment history array with full establishment records', function () {",
                  "    const d = pm.response.json().data;",
                  "    pm.expect(d.employment_history).to.be.an('array');",
                  "    d.employment_history.forEach(function (job) {",
                  "        pm.expect(job).to.have.property('member_id');",
                  "        pm.expect(job).to.have.property('establishment_id');",
                  "        pm.expect(job).to.have.property('establishment_name');",
                  "        pm.expect(job).to.have.property('employment_status');",
                  "    });",
                  "});",
                  "",
                  "pm.test('Dual-employment / moonlighting analysis present', function () {",
                  "    const d = pm.response.json().data;",
                  "    pm.expect(d.dual_employment_detected).to.be.a('boolean');",
                  "    pm.expect(d.moonlighting_risk_score).to.be.a('number').within(0, 100);",
                  "    if (d.dual_employment_detected) {",
                  "        pm.expect(d.concurrent_establishments).to.be.an('array').with.length.above(1);",
                  "    }",
                  "});",
                  "",
                  "pm.test('Member IDs are unique across the employment trail', function () {",
                  "    const jobs = pm.response.json().data.employment_history;",
                  "    const ids = jobs.map(function (j) { return j.member_id; });",
                  "    pm.expect(new Set(ids).size).to.eql(ids.length);",
                  "});",
                  "",
                  "pm.test('Active tenure carries recent-contribution recency', function () {",
                  "    const active = pm.response.json().data.employment_history.filter(function (j) { return j.employment_status === 'ACTIVE'; });",
                  "    active.forEach(function (job) {",
                  "        pm.expect(job.contribution_months_last_12).to.be.at.least(1);",
                  "    });",
                  "});"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "x-api-key",
                "value": "{{API_KEY}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"request_id\": \"{{REQUEST_ID}}\",\n  \"timestamp\": \"{{TIMESTAMP}}\",\n  \"consent\": true,\n  \"consent_text\": \"I hereby authorize ASP Associates to retrieve my EPFO employment history associated with my Universal Account Number for background verification purposes.\",\n  \"uan\": \"101010101010\",\n  \"include_member_ids\": true,\n  \"detect_dual_employment\": true,\n  \"lookback_months\": 36\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{BASE_URL}}/api/v1/gateway/uan-employment-v3",
              "host": [
                "{{BASE_URL}}"
              ],
              "path": [
                "api",
                "v1",
                "gateway",
                "uan-employment-v3"
              ]
            },
            "description": "### EPFO UAN Employment History v3\nPulls the complete EPFO employment trail for a UAN: every Member ID \u2194 establishment mapping, DOJ/DOE, contribution recency over the trailing 12 months, plus **dual-employment detection** (overlapping active tenures across establishments \u2192 moonlighting signal with a 0\u2013100 risk score).\n\n\u26a0\ufe0f **Timeout budget: 40 s.** The EPFO gateway is batch-oriented; configure client timeouts \u2265 45 s.\n\n**Request schema**\n```json\n{\n  \"uan\": \"12-digit string\",\n  \"include_member_ids\": true,\n  \"detect_dual_employment\": true,\n  \"lookback_months\": 36\n}\n```\n\n**Key response fields**\n```json\n{\n  \"data\": {\n    \"employment_history\": [\n      {\n        \"member_id\": \"DL/CPM/0012345/000\",\n        \"establishment_id\": \"string\",\n        \"establishment_name\": \"string\",\n        \"date_of_joining\": \"YYYY-MM-DD\",\n        \"date_of_exit\": \"YYYY-MM-DD | null\",\n        \"employment_status\": \"ACTIVE | CLOSED\",\n        \"contribution_months_last_12\": 12\n      }\n    ],\n    \"dual_employment_detected\": false,\n    \"moonlighting_risk_score\": 4\n  }\n}\n```"
          },
          "response": [
            {
              "name": "200 OK \u2014 Two establishments, no dual employment",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  },
                  {
                    "key": "x-api-key",
                    "value": "{{API_KEY}}"
                  }
                ],
                "url": {
                  "raw": "{{BASE_URL}}/api/v1/gateway/uan-employment-v3",
                  "host": [
                    "{{BASE_URL}}"
                  ],
                  "path": [
                    "api",
                    "v1",
                    "gateway",
                    "uan-employment-v3"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"request_id\": \"{{REQUEST_ID}}\",\n  \"timestamp\": \"{{TIMESTAMP}}\",\n  \"consent\": true,\n  \"consent_text\": \"I hereby authorize ASP Associates to retrieve my EPFO employment history associated with my Universal Account Number for background verification purposes.\",\n  \"uan\": \"101010101010\",\n  \"include_member_ids\": true,\n  \"detect_dual_employment\": true,\n  \"lookback_months\": 36\n}"
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"success\": true,\n  \"request_id\": \"req_e6p4lm_z9c2wa\",\n  \"data\": {\n    \"uan_masked\": \"XXXXXXXX1010\",\n    \"member_name\": \"SHUBHAM SHARMA\",\n    \"employment_history\": [\n      {\n        \"member_id\": \"DL/CPM/0012345/000\",\n        \"establishment_id\": \"DLCPE0012345000\",\n        \"establishment_name\": \"TECHNOLOGY SOLUTIONS PRIVATE LIMITED\",\n        \"date_of_joining\": \"2021-04-12\",\n        \"date_of_exit\": null,\n        \"employment_status\": \"ACTIVE\",\n        \"contribution_months_last_12\": 12\n      },\n      {\n        \"member_id\": \"PY/KRK/0098765/000\",\n        \"establishment_id\": \"PYKRK0098765000\",\n        \"establishment_name\": \"PREVIOUS EMPLOYER SERVICES LLP\",\n        \"date_of_joining\": \"2018-07-01\",\n        \"date_of_exit\": \"2021-03-31\",\n        \"employment_status\": \"CLOSED\",\n        \"contribution_months_last_12\": 0\n      }\n    ],\n    \"total_establishments\": 2,\n    \"dual_employment_detected\": false,\n    \"concurrent_establishments\": [],\n    \"moonlighting_risk_score\": 4,\n    \"gateway_latency_ms\": 21340,\n    \"checked_at\": \"2025-06-01T10:02:39Z\"\n  },\n  \"meta\": {\n    \"latency_ms\": 21405,\n    \"credits_consumed\": 3\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "3. Financial Intelligence",
      "description": "Counterparty financial-integrity checks powered by NPCI rails:\n- **Bank Account Penny Drop** \u2014 \u20b91.00 IMPS transfer proves account existence and harvests the beneficiary bank's legal registered name.\n- **UPI VPA Validation** \u2014 resolves Virtual Payment Address existence and the registered payee name at the PSP handle.",
      "item": [
        {
          "name": "Bank Account Penny Drop (NPCI IMPS)",
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const body = JSON.parse(pm.request.body.raw);",
                  "const ifsc = String(body.ifsc || '').trim().toUpperCase();",
                  "const acct = String(body.account_number || '').trim();",
                  "",
                  "// IFSC: 4 bank-alpha + mandatory 0 at position 5 + 6 alphanumeric.",
                  "if (!/^[A-Z]{4}0[A-Z0-9]{6}$/.test(ifsc)) {",
                  "    throw new Error('Invalid IFSC [' + ifsc + ']. Format: 4 bank letters + 0 + 6 alphanumeric (e.g., HDFC0001234).');",
                  "}",
                  "",
                  "if (!/^[0-9]{9,18}$/.test(acct)) {",
                  "    throw new Error('Account number must be 9-18 digits.');",
                  "}",
                  "",
                  "pm.collectionVariables.set('IFSC_BANK_ALPHA', ifsc.slice(0, 4));"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('HTTP 200 OK', function () {",
                  "    pm.response.to.have.status(200);",
                  "});",
                  "",
                  "pm.test('IMPS penny-drop settlement outcome recorded with UTR', function () {",
                  "    const d = pm.response.json().data;",
                  "    pm.expect(d.transfer_status).to.be.oneOf(['COMPLETED', 'FAILED', 'SUSPENDED_ACCOUNT']);",
                  "    pm.expect(d.utr_reference).to.be.a('string').and.not.empty;",
                  "});",
                  "",
                  "pm.test('Account existence confirmed at beneficiary bank', function () {",
                  "    pm.expect(pm.response.json().data.account_exists).to.be.a('boolean');",
                  "});",
                  "",
                  "pm.test('Legal name retrieved and fuzzy-matched against supplied name', function () {",
                  "    const d = pm.response.json().data;",
                  "    pm.expect(d.beneficiary_legal_name).to.be.a('string').and.not.empty;",
                  "    pm.expect(d.name_match_score).to.be.at.least(80);",
                  "});",
                  "",
                  "pm.test('Exactly one rupee was moved (penny-drop invariant)', function () {",
                  "    pm.expect(pm.response.json().data.amount).to.eql(1.00);",
                  "    pm.expect(pm.response.json().data.settlement_channel).to.eql('IMPS');",
                  "});",
                  "",
                  "pm.test('Beneficiary bank and branch resolved from IFSC', function () {",
                  "    const d = pm.response.json().data;",
                  "    pm.expect(d.bank_name).to.exist;",
                  "    pm.expect(d.branch).to.exist;",
                  "});"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "x-api-key",
                "value": "{{API_KEY}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"request_id\": \"{{REQUEST_ID}}\",\n  \"timestamp\": \"{{TIMESTAMP}}\",\n  \"consent\": true,\n  \"consent_text\": \"I hereby consent to ASP Associates initiating a nominal-value IMPS transfer to my bank account to verify its existence and registered beneficiary name.\",\n  \"account_number\": \"50100234567890\",\n  \"ifsc\": \"HDFC0001234\",\n  \"beneficiary_name\": \"Shubham Sharma\",\n  \"penny_amount\": 1.00,\n  \"transfer_mode\": \"IMPS\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{BASE_URL}}/api/v1/verify/bank-account",
              "host": [
                "{{BASE_URL}}"
              ],
              "path": [
                "api",
                "v1",
                "verify",
                "bank-account"
              ]
            },
            "description": "### Bank Account \u2014 NPCI IMPS Penny Drop\nTransfers \u20b91.00 via IMPS to prove account existence and harvest the **legal registered name** from the beneficiary bank. Name-match scoring surfaces mule-account risk on mismatch.\n\n**IFSC format**: `^[A-Z]{4}0[A-Z0-9]{6}$` \u2014 the 5th character is always `0`.\n\n**Request schema**\n```json\n{\n  \"account_number\": \"9-18 digits\",\n  \"ifsc\": \"HDFC0001234\",\n  \"beneficiary_name\": \"string\",\n  \"penny_amount\": 1.00,\n  \"transfer_mode\": \"IMPS\"\n}\n```"
          },
          "response": [
            {
              "name": "200 OK \u2014 Account exists, name matched",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  },
                  {
                    "key": "x-api-key",
                    "value": "{{API_KEY}}"
                  }
                ],
                "url": {
                  "raw": "{{BASE_URL}}/api/v1/verify/bank-account",
                  "host": [
                    "{{BASE_URL}}"
                  ],
                  "path": [
                    "api",
                    "v1",
                    "verify",
                    "bank-account"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"request_id\": \"{{REQUEST_ID}}\",\n  \"timestamp\": \"{{TIMESTAMP}}\",\n  \"consent\": true,\n  \"consent_text\": \"I hereby consent to ASP Associates initiating a nominal-value IMPS transfer to my bank account to verify its existence and registered beneficiary name.\",\n  \"account_number\": \"50100234567890\",\n  \"ifsc\": \"HDFC0001234\",\n  \"beneficiary_name\": \"Shubham Sharma\",\n  \"penny_amount\": 1.00,\n  \"transfer_mode\": \"IMPS\"\n}"
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"success\": true,\n  \"request_id\": \"req_f1rs9t_a4d6yu\",\n  \"data\": {\n    \"account_number_masked\": \"XXXXXXX7890\",\n    \"ifsc\": \"HDFC0001234\",\n    \"bank_name\": \"HDFC BANK LTD\",\n    \"branch\": \"NEW DELHI - MODEL TOWN\",\n    \"transfer_status\": \"COMPLETED\",\n    \"account_exists\": true,\n    \"beneficiary_legal_name\": \"SHUBHAM SHARMA\",\n    \"name_match_score\": 97,\n    \"amount\": 1.00,\n    \"utr_reference\": \"HDFCR52025060112345678\",\n    \"settlement_channel\": \"IMPS\",\n    \"checked_at\": \"2025-06-01T10:06:55Z\"\n  },\n  \"meta\": {\n    \"latency_ms\": 3420,\n    \"credits_consumed\": 2\n  }\n}"
            }
          ]
        },
        {
          "name": "Validate UPI VPA",
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const body = JSON.parse(pm.request.body.raw);",
                  "const vpa = String(body.vpa || '').trim().toLowerCase();",
                  "",
                  "// VPA: local-part @ PSP-handle (e.g., shubham@okhdfcbank).",
                  "if (!/^[a-zA-Z0-9._-]{2,256}@[a-zA-Z][a-zA-Z0-9.-]{1,64}$/.test(vpa)) {",
                  "    throw new Error('Invalid VPA format. Expected handle like name@psp (e.g., shubham@okhdfcbank).');",
                  "}",
                  "",
                  "pm.collectionVariables.set('VPA_HANDLE', vpa.split('@')[1]);"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('HTTP 200 OK', function () {",
                  "    pm.response.to.have.status(200);",
                  "});",
                  "",
                  "pm.test('VPA existence resolved by the PSP', function () {",
                  "    pm.expect(pm.response.json().data.vpa_exists).to.be.a('boolean');",
                  "});",
                  "",
                  "pm.test('Registered payee name returned for display-name matching', function () {",
                  "    const d = pm.response.json().data;",
                  "    pm.expect(d.registered_name).to.be.a('string').and.not.empty;",
                  "    pm.expect(d.name_match_score).to.be.a('number');",
                  "});",
                  "",
                  "pm.test('PSP handle correctly identified from VPA', function () {",
                  "    pm.expect(pm.response.json().data.psp_handle).to.eql(pm.collectionVariables.get('VPA_HANDLE'));",
                  "});"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "x-api-key",
                "value": "{{API_KEY}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"request_id\": \"{{REQUEST_ID}}\",\n  \"timestamp\": \"{{TIMESTAMP}}\",\n  \"consent\": true,\n  \"consent_text\": \"I hereby consent to ASP Associates validating my UPI Virtual Payment Address with the relevant Payment Service Provider.\",\n  \"vpa\": \"shubham@okhdfcbank\",\n  \"beneficiary_name\": \"Shubham Sharma\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{BASE_URL}}/api/v1/verify/upi-vpa",
              "host": [
                "{{BASE_URL}}"
              ],
              "path": [
                "api",
                "v1",
                "verify",
                "upi-vpa"
              ]
            },
            "description": "### UPI VPA Validation\nResolves whether a Virtual Payment Address exists at its PSP handle and returns the registered payee name for display-name verification \u2014 the primary defence against payment-to-wrong-VPA fraud.\n\n**Request schema**\n```json\n{\n  \"vpa\": \"shubham@okhdfcbank\",\n  \"beneficiary_name\": \"string\"\n}\n```"
          },
          "response": [
            {
              "name": "200 OK \u2014 VPA exists at okhdfcbank",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  },
                  {
                    "key": "x-api-key",
                    "value": "{{API_KEY}}"
                  }
                ],
                "url": {
                  "raw": "{{BASE_URL}}/api/v1/verify/upi-vpa",
                  "host": [
                    "{{BASE_URL}}"
                  ],
                  "path": [
                    "api",
                    "v1",
                    "verify",
                    "upi-vpa"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"request_id\": \"{{REQUEST_ID}}\",\n  \"timestamp\": \"{{TIMESTAMP}}\",\n  \"consent\": true,\n  \"consent_text\": \"I hereby consent to ASP Associates validating my UPI Virtual Payment Address with the relevant Payment Service Provider.\",\n  \"vpa\": \"shubham@okhdfcbank\",\n  \"beneficiary_name\": \"Shubham Sharma\"\n}"
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"success\": true,\n  \"request_id\": \"req_g8uv2x_b7e3io\",\n  \"data\": {\n    \"vpa\": \"shubham@okhdfcbank\",\n    \"vpa_exists\": true,\n    \"registered_name\": \"Shubham Sharma\",\n    \"name_match_score\": 95,\n    \"psp_handle\": \"okhdfcbank\",\n    \"psp_bank\": \"HDFC Bank\",\n    \"checked_at\": \"2025-06-01T10:09:20Z\"\n  },\n  \"meta\": {\n    \"latency_ms\": 890,\n    \"credits_consumed\": 1\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "4. Business & Tax",
      "description": "GST registry intelligence: local state-prefix decoding happens in the pre-request script (free), while taxpayer status, legal/trade names, constitution, and rolling GSTR-3B filing behaviour come from the live registry.",
      "item": [
        {
          "name": "Verify GSTIN (+ GSTR-3B History)",
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const body = JSON.parse(pm.request.body.raw);",
                  "const gstin = String(body.gstin || '').trim().toUpperCase();",
                  "",
                  "// Structure: 2-digit state + 10-char PAN + entity digit + Z + checksum.",
                  "if (!/^[0-9]{2}[A-Z]{5}[0-9]{4}[A-Z][1-9A-Z]Z[0-9A-Z]$/.test(gstin)) {",
                  "    throw new Error('Invalid GSTIN structure. Expected 15 chars: 2-digit state code + PAN + entity digit + Z + checksum.');",
                  "}",
                  "",
                  "// Decode the first two digits into the registering state (GST state codes).",
                  "const stateCodes = {",
                  "    '01': 'Jammu and Kashmir', '02': 'Himachal Pradesh', '03': 'Punjab', '04': 'Chandigarh',",
                  "    '05': 'Uttarakhand', '06': 'Haryana', '07': 'Delhi', '08': 'Rajasthan', '09': 'Uttar Pradesh',",
                  "    '10': 'Bihar', '11': 'Sikkim', '12': 'Arunachal Pradesh', '13': 'Nagaland', '14': 'Manipur',",
                  "    '15': 'Mizoram', '16': 'Tripura', '17': 'Meghalaya', '18': 'Assam', '19': 'West Bengal',",
                  "    '20': 'Jharkhand', '21': 'Odisha', '22': 'Chhattisgarh', '23': 'Madhya Pradesh', '24': 'Gujarat',",
                  "    '26': 'Dadra and Nagar Haveli and Daman and Diu', '27': 'Maharashtra', '29': 'Karnataka',",
                  "    '30': 'Goa', '31': 'Lakshadweep', '32': 'Kerala', '33': 'Tamil Nadu', '34': 'Puducherry',",
                  "    '35': 'Andaman and Nicobar Islands', '36': 'Telangana', '37': 'Andhra Pradesh', '38': 'Ladakh'",
                  "};",
                  "",
                  "const stateCode = gstin.slice(0, 2);",
                  "const stateName = stateCodes[stateCode];",
                  "",
                  "if (!stateName) {",
                  "    throw new Error('Unrecognized GST state code prefix: ' + stateCode);",
                  "}",
                  "",
                  "pm.collectionVariables.set('GST_STATE_CODE', stateCode);",
                  "pm.collectionVariables.set('GST_STATE_NAME', stateName);",
                  "console.log('Decoded registering state: [' + stateCode + '] ' + stateName);"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('HTTP 200 OK', function () {",
                  "    pm.response.to.have.status(200);",
                  "});",
                  "",
                  "pm.test('Taxpayer status enumerated', function () {",
                  "    const d = pm.response.json().data;",
                  "    pm.expect(d.taxpayer_status).to.be.oneOf(['ACTIVE', 'CANCELLED', 'SUSPENDED', 'PROVISIONAL', 'NOT_FOUND']);",
                  "});",
                  "",
                  "pm.test('State decoder agrees with registered principal place of business', function () {",
                  "    const d = pm.response.json().data;",
                  "    pm.expect(d.state_code).to.eql(pm.collectionVariables.get('GST_STATE_CODE'));",
                  "    pm.expect(d.state_name).to.eql(pm.collectionVariables.get('GST_STATE_NAME'));",
                  "});",
                  "",
                  "pm.test('GSTR-3B filing history returned for requested window', function () {",
                  "    const d = pm.response.json().data;",
                  "    pm.expect(d.gstr3b_filing_history).to.be.an('array');",
                  "    pm.expect(d.gstr3b_filing_history.length).to.be.at.most(12);",
                  "    d.gstr3b_filing_history.forEach(function (period) {",
                  "        pm.expect(period).to.have.property('return_period');",
                  "        pm.expect(['FILED', 'NOT_FILED', 'LATE_FEE_PAID']).to.include(period.filing_status);",
                  "    });",
                  "});",
                  "",
                  "pm.test('Legal name, trade name, and constitution captured', function () {",
                  "    const d = pm.response.json().data;",
                  "    pm.expect(d.legal_name).to.exist;",
                  "    pm.expect(d.trade_name).to.exist;",
                  "    pm.expect(d.constitution_of_business).to.exist;",
                  "});",
                  "",
                  "pm.test('Compliance score bounded 0-100', function () {",
                  "    pm.expect(pm.response.json().data.compliance_score).to.be.within(0, 100);",
                  "});"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "x-api-key",
                "value": "{{API_KEY}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"request_id\": \"{{REQUEST_ID}}\",\n  \"timestamp\": \"{{TIMESTAMP}}\",\n  \"consent\": true,\n  \"consent_text\": \"I hereby consent to ASP Associates verifying GST registration and filing compliance details for the stated GSTIN.\",\n  \"gstin\": \"07AAAPL1234C1ZV\",\n  \"business_name\": \"Apple India Private Limited\",\n  \"include_gstr3b_history\": true,\n  \"history_months\": 12\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{BASE_URL}}/api/v1/verify/gstin",
              "host": [
                "{{BASE_URL}}"
              ],
              "path": [
                "api",
                "v1",
                "verify",
                "gstin"
              ]
            },
            "description": "### GSTIN Verification\nDecodes the 2-digit state prefix locally (pre-request, zero cost), then queries the GST registry for taxpayer status, legal/trade names, constitution of business, taxpayer type, registration date, and rolling **GSTR-3B filing history** with a derived 0\u2013100 compliance score.\n\n**Request schema**\n```json\n{\n  \"gstin\": \"07AAAPL1234C1ZV\",\n  \"business_name\": \"string\",\n  \"include_gstr3b_history\": true,\n  \"history_months\": 12\n}\n```"
          },
          "response": [
            {
              "name": "200 OK \u2014 Active taxpayer, filings healthy",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  },
                  {
                    "key": "x-api-key",
                    "value": "{{API_KEY}}"
                  }
                ],
                "url": {
                  "raw": "{{BASE_URL}}/api/v1/verify/gstin",
                  "host": [
                    "{{BASE_URL}}"
                  ],
                  "path": [
                    "api",
                    "v1",
                    "verify",
                    "gstin"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"request_id\": \"{{REQUEST_ID}}\",\n  \"timestamp\": \"{{TIMESTAMP}}\",\n  \"consent\": true,\n  \"consent_text\": \"I hereby consent to ASP Associates verifying GST registration and filing compliance details for the stated GSTIN.\",\n  \"gstin\": \"07AAAPL1234C1ZV\",\n  \"business_name\": \"Apple India Private Limited\",\n  \"include_gstr3b_history\": true,\n  \"history_months\": 12\n}"
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"success\": true,\n  \"request_id\": \"req_h3io7p_c1m9xz\",\n  \"data\": {\n    \"gstin\": \"07AAAPL1234C1ZV\",\n    \"taxpayer_status\": \"ACTIVE\",\n    \"legal_name\": \"APPLE INDIA PRIVATE LIMITED\",\n    \"trade_name\": \"APPLE INDIA\",\n    \"constitution_of_business\": \"PRIVATE LIMITED COMPANY\",\n    \"taxpayer_type\": \"REGULAR\",\n    \"state_code\": \"07\",\n    \"state_name\": \"Delhi\",\n    \"registration_date\": \"2017-07-01\",\n    \"gstr3b_filing_history\": [\n      {\n        \"return_period\": \"2025-04\",\n        \"filing_status\": \"FILED\",\n        \"filed_on\": \"2025-05-18\",\n        \"arn\": \"AA070625123456X\"\n      },\n      {\n        \"return_period\": \"2025-03\",\n        \"filing_status\": \"FILED\",\n        \"filed_on\": \"2025-04-17\",\n        \"arn\": \"AA070425987654W\"\n      }\n    ],\n    \"compliance_score\": 92,\n    \"checked_at\": \"2025-06-01T10:12:44Z\"\n  },\n  \"meta\": {\n    \"latency_ms\": 2260,\n    \"credits_consumed\": 2\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "5. Mobility & Assets",
      "description": "Asset-integrity checks against MoRTH Vahan 2.0: ownership, vehicle attributes, financier liens (hypothecation), fitness validity, insurance posture, and odometer snapshots \u2014 the standard stack for used-vehicle lending and fleet onboarding.",
      "item": [
        {
          "name": "Verify Vehicle RC (Vahan 2.0)",
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const body = JSON.parse(pm.request.body.raw);",
                  "const reg = String(body.registration_number || '').toUpperCase().replace(/[^A-Z0-9]/g, '');",
                  "",
                  "// Broad Indian VRM pattern: 2 state letters + 1-2 district digits +",
                  "// 0-3 series letters + 4 chassis digits (e.g., DL01AB1234).",
                  "if (!/^[A-Z]{2}[0-9]{1,2}[A-Z]{0,3}[0-9]{4}$/.test(reg)) {",
                  "    throw new Error('Registration number does not look like a valid Indian VRM (e.g., DL01AB1234). Received: ' + reg);",
                  "}",
                  "",
                  "pm.collectionVariables.set('RC_NORMALIZED', reg);"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('HTTP 200 OK', function () {",
                  "    pm.response.to.have.status(200);",
                  "});",
                  "",
                  "pm.test('RC fetched from Vahan with core vehicle attributes', function () {",
                  "    const d = pm.response.json().data;",
                  "    pm.expect(d.registration_status).to.be.oneOf(['ACTIVE', 'SCRAPPED', 'TRANSFERRED', 'NOT_FOUND']);",
                  "    pm.expect(d.make_model).to.exist;",
                  "    pm.expect(['PETROL', 'DIESEL', 'CNG', 'LPG', 'HYBRID', 'ELECTRIC', 'OTHER']).to.include(d.fuel_type);",
                  "    pm.expect(d.registration_date).to.exist;",
                  "});",
                  "",
                  "pm.test('Hypothecation (financier lien) block evaluated', function () {",
                  "    const d = pm.response.json().data;",
                  "    pm.expect(d).to.have.property('hypothecation');",
                  "    if (d.hypothecation && d.hypothecation.is_hypothecated === true) {",
                  "        pm.expect(d.hypothecation.financier_name).to.be.a('string').and.not.empty;",
                  "    }",
                  "});",
                  "",
                  "pm.test('Fitness validity parsed with expiry flag', function () {",
                  "    const d = pm.response.json().data;",
                  "    pm.expect(d.fitness_upto).to.exist;",
                  "    pm.expect(d.fitness_expired).to.be.a('boolean');",
                  "});",
                  "",
                  "pm.test('Insurance policy block with type and expiry', function () {",
                  "    const ins = pm.response.json().data.insurance;",
                  "    pm.expect(ins.policy_type).to.be.oneOf(['THIRD_PARTY', 'COMPREHENSIVE', 'OWN_DAMAGE', 'UNKNOWN']);",
                  "    pm.expect(ins.policy_expiry).to.exist;",
                  "});",
                  "",
                  "pm.test('Chassis and engine numbers masked in transit', function () {",
                  "    const d = pm.response.json().data;",
                  "    pm.expect(d.chassis_number_masked).to.match(/\\*/);",
                  "    pm.expect(d.engine_number_masked).to.match(/\\*/);",
                  "});"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "x-api-key",
                "value": "{{API_KEY}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"request_id\": \"{{REQUEST_ID}}\",\n  \"timestamp\": \"{{TIMESTAMP}}\",\n  \"consent\": true,\n  \"consent_text\": \"I hereby consent to ASP Associates fetching my vehicle Registration Certificate details from the Ministry of Road Transport and Highways (Vahan) database.\",\n  \"registration_number\": \"DL01AB1234\",\n  \"include_hypothecation\": true,\n  \"include_fitness\": true,\n  \"include_insurance\": true\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{BASE_URL}}/api/v1/verify/rc",
              "host": [
                "{{BASE_URL}}"
              ],
              "path": [
                "api",
                "v1",
                "verify",
                "rc"
              ]
            },
            "description": "### Vehicle RC \u2014 MoRTH Vahan 2.0\nFull registration-certificate pull: owner, make/model/variant/fuel/class, masked chassis & engine numbers, **hypothecation (financier lien)** status, fitness validity, insurance policy block, and last-recorded odometer reading.\n\n**Request schema**\n```json\n{\n  \"registration_number\": \"DL01AB1234\",\n  \"include_hypothecation\": true,\n  \"include_fitness\": true,\n  \"include_insurance\": true\n}\n```"
          },
          "response": [
            {
              "name": "200 OK \u2014 Active RC, no lien, insured",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  },
                  {
                    "key": "x-api-key",
                    "value": "{{API_KEY}}"
                  }
                ],
                "url": {
                  "raw": "{{BASE_URL}}/api/v1/verify/rc",
                  "host": [
                    "{{BASE_URL}}"
                  ],
                  "path": [
                    "api",
                    "v1",
                    "verify",
                    "rc"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"request_id\": \"{{REQUEST_ID}}\",\n  \"timestamp\": \"{{TIMESTAMP}}\",\n  \"consent\": true,\n  \"consent_text\": \"I hereby consent to ASP Associates fetching my vehicle Registration Certificate details from the Ministry of Road Transport and Highways (Vahan) database.\",\n  \"registration_number\": \"DL01AB1234\",\n  \"include_hypothecation\": true,\n  \"include_fitness\": true,\n  \"include_insurance\": true\n}"
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"success\": true,\n  \"request_id\": \"req_i5kl1q_d8n4vb\",\n  \"data\": {\n    \"registration_number\": \"DL01AB1234\",\n    \"registration_status\": \"ACTIVE\",\n    \"owner_name\": \"SHUBHAM SHARMA\",\n    \"owner_type\": \"INDIVIDUAL\",\n    \"make_model\": \"MARUTI SUZUKI BALENO ZETA\",\n    \"variant\": \"1.2 PETROL\",\n    \"fuel_type\": \"PETROL\",\n    \"vehicle_class\": \"LMV-CAR\",\n    \"color\": \"PEARL WHITE\",\n    \"registration_date\": \"2019-03-18\",\n    \"chassis_number_masked\": \"MA3EJ********4210\",\n    \"engine_number_masked\": \"K12M*****8891\",\n    \"hypothecation\": {\n      \"is_hypothecated\": false,\n      \"financier_name\": null,\n      \"lien_start_date\": null,\n      \"lien_end_date\": null\n    },\n    \"fitness_upto\": \"2034-03-17\",\n    \"fitness_expired\": false,\n    \"insurance\": {\n      \"policy_type\": \"COMPREHENSIVE\",\n      \"insurer\": \"ICICI LOMBARD GENERAL INSURANCE\",\n      \"policy_number_masked\": \"3005/MOT/******21\",\n      \"policy_expiry\": \"2026-03-17\"\n    },\n    \"odometer_last_recorded_km\": 48210,\n    \"source\": \"MORTH_VAHAN_2_0\",\n    \"checked_at\": \"2025-06-01T10:16:08Z\"\n  },\n  \"meta\": {\n    \"latency_ms\": 2890,\n    \"credits_consumed\": 2\n  }\n}"
            }
          ]
        }
      ]
    }
  ]
}