Skip to main content

Documentation Index

Fetch the complete documentation index at: https://casparser.in/docs/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The KYC PAN Status API queries the CVL KRA public portal to retrieve KYC registration status for a given PAN number across all five SEBI-registered KRAs (CVL, NDML, CAMS, Karvy, KFin). What you get:
  • A normalized kyc_status enum — no raw portal strings to parse
  • A single kyc_compliant boolean for quick onboarding gate decisions
  • Per-KRA breakdown with dates, mode, and remarks
What you need:
  • PAN number (10 characters)
This endpoint queries the CVL KRA portal and may take up to 60 seconds. Set your client timeout to at least 60 seconds.

Quick example

import requests

response = requests.post(
    "https://api.casparser.in/v1/kyc/pan/status",
    headers={"x-api-key": "YOUR_API_KEY"},
    json={"pan_no": "ABCDE1234F"},
    timeout=60
)

data = response.json()

if data["kyc_compliant"]:
    print(f"KYC verified — status: {data['kyc_status']}, KRA: {data['active_kra']}")
else:
    print(f"KYC not compliant — status: {data['kyc_status']}")

Response structure

{
  "status": "success",
  "pan": "ABCDE1234F",
  "kyc_compliant": true,
  "kyc_status": "validated",
  "kyc_mode": "digilocker",
  "active_kra": "cvl",
  "registered_on": "2020-07-02",
  "last_updated_on": "2024-09-19",
  "kras": {
    "cvl": {
      "status": "validated",
      "registered_on": "2020-07-02",
      "last_updated_on": "2024-09-19",
      "kyc_mode": "digilocker",
      "remarks": null,
      "raw_status": null
    },
    "ndml": {
      "status": "not_available",
      "registered_on": null,
      "last_updated_on": null,
      "kyc_mode": null,
      "remarks": null,
      "raw_status": null
    },
    "cams":  { "status": "not_checked", ... },
    "karvy": { "status": "not_checked", ... },
    "kfin":  { "status": "not_checked", ... }
  }
}
All six keys on every KRA object are always present — null when not applicable.

kyc_status values

StatusMeaningkyc_compliant
validatedKYC complete, investor can transact freelytrue
registeredKYC registered; some restrictions may apply — check your platform’s policytrue
under_processRecently submitted, still being processed by KRAfalse
on_holdDiscrepancy detected — check remarks on the KRA objectfalse
rejectedKYC rejected — investor must submit fresh KYCfalse
legacyOld/incomplete record — re-KYC recommendedfalse
not_availableKRA was queried but has no record for this PANfalse
not_checkedKRA was not queried by the portalfalse
unknownUnrecognized portal string — raw_status field preservedfalse

Handling on_hold

When kyc_status is on_hold, check remarks on the active KRA object for the reason:
data = response.json()

if data["kyc_status"] == "on_hold":
    active = data["active_kra"]
    remarks = data["kras"][active]["remarks"]
    # e.g. "APPLICANT PHOTO MISMATCH IN THE APPLICATION"
    print(f"KYC on hold: {remarks}")
remarks may contain multiple comma-separated reasons (e.g. "APPLICANT PHOTO MISMATCH IN THE APPLICATION,FATCA NOT APPLICABLE"). FATCA NOT APPLICABLE is informational and not an error.

raw_status field

For exact-matched statuses (the common case), raw_status is null. raw_status is non-null when the portal returned a string the API hadn’t seen before and used a fuzzy match instead of an exact one. If you see a non-null raw_status in production, please report it so we can add it to the exact map.

Full example

import requests

API_KEY = "YOUR_API_KEY"

def check_kyc_status(pan: str) -> dict:
    """
    Check KYC status for a PAN number.
    
    Returns the normalized response or raises on error.
    """
    response = requests.post(
        "https://api.casparser.in/v1/kyc/pan/status",
        headers={"x-api-key": API_KEY},
        json={"pan_no": pan},
        timeout=60  # CVL KRA portal queries can take up to 60s
    )
    response.raise_for_status()
    return response.json()


# Basic onboarding gate
data = check_kyc_status("ABCDE1234F")

if data["kyc_compliant"]:
    # Allow onboarding
    print(f"KYC verified ({data['kyc_status']}) via {data['active_kra'].upper()} KRA")
    print(f"Registered on: {data['registered_on']}")
else:
    status = data["kyc_status"]
    if status == "on_hold":
        active = data["active_kra"]
        remarks = data["kras"][active]["remarks"]
        print(f"KYC on hold — reason: {remarks}")
    elif status == "not_available":
        print("No KYC record found. Investor needs to complete KYC.")
    elif status == "rejected":
        print("KYC rejected. Investor must submit fresh KYC.")
    elif status == "under_process":
        print("KYC is being processed. Check again later.")
    elif status == "legacy":
        print("Old KYC record. Re-KYC recommended.")
    else:
        print(f"KYC status: {status}")

Credit usage

OperationCredits
Successful lookup0.5
Failed lookup (any error)0

Error handling

HTTP statusCauseAction
400pan_no missing or emptyValidate request body
401Invalid or missing API keyCheck x-api-key header
503CVL KRA service unavailableRetry with exponential backoff
504CVL KRA portal timed outRetry with exponential backoff
try:
    data = check_kyc_status("ABCDE1234F")
except requests.exceptions.Timeout:
    print("Request timed out — CVL KRA portal is slow. Retry.")
except requests.exceptions.HTTPError as e:
    if e.response.status_code in (503, 504):
        print("KYC service unavailable — retry in a few seconds")
    else:
        raise

Next steps

CAS Parsing

Parse portfolio statements after KYC is verified

CDSL OTP Fetch

Fetch CAS files directly from CDSL