How to Find Client Mutual Funds Held Under a Different ARN Code
MF distributors: find client holdings sitting under another distributor's ARN code using the CAS Parser API. Spot AUM you didn't know existed, then file a Change of Broker.
If you’re an MF distributor or RIA, you’ve probably had this moment: the AUM figure in your back-office dashboard doesn’t match what the client thinks their portfolio is worth. Usually it’s not a data error. It’s a fund the client bought through someone else — a bank RM, an old platform, before you ever met them — and never mentioned.
That information has been sitting in their CAS the entire time. Nobody reads a CAS line by line across an entire client book to check for it, so it stays invisible.
There’s a field in the data built for exactly this. It’s just easier to see once the CAS is JSON instead of a PDF.
What the ARN code field actually shows you
Every mutual fund scheme in a CAMS or KFintech CAS is tagged with the ARN of whoever gets paid commission on it: ARN-12345, a distributor’s registered name, or DIRECT if the client bought it themselves with no distributor attached. AMFI requires RTAs to track this so trail commission lands with the right person, which is why it’s printed directly on the statement.
When CASParser parses a CAMS or KFintech CAS, this shows up as additional_info.advisor on each scheme. Mutual fund units held in demat form carry the same information under a different key, additional_info.arn_code.
Comparing a client’s ARN codes against your own
Once the CAS is parsed, this stops being a manual read-through and becomes a filter: loop through every scheme in every folio, pull the ARN code, and flag anything that isn’t yours and isn’t DIRECT.
import requests
MY_ARN = "ARN-12345" # your own distributor code
response = requests.post(
"https://api.casparser.in/v4/smart/parse",
headers={"x-api-key": API_KEY},
files={"pdf_file": open("client_cas.pdf", "rb")},
data={"password": pdf_password},
)
data = response.json()
held_elsewhere = []
for folio in data["mutual_funds"]:
for scheme in folio["schemes"]:
info = scheme.get("additional_info", {})
code = (info.get("advisor") or info.get("arn_code") or "").strip().upper()
if code and MY_ARN not in code and "DIRECT" not in code:
held_elsewhere.append({
"amc": folio["amc"],
"folio": folio["folio_number"],
"scheme": scheme["name"],
"value": scheme["value"],
"held_with": code,
})
Run this against your whole book instead of one PDF and held_elsewhere turns into a list you can actually work: which client, which scheme, how much it’s worth, and whose ARN is currently attached to it.
[
{
"amc": "HDFC Mutual Fund",
"folio": "12345678/01",
"scheme": "HDFC Balanced Advantage Fund - Regular Plan - Growth",
"value": 185000,
"held_with": "ARN-67890"
},
{
"amc": "SBI Mutual Fund",
"folio": "98765432/02",
"scheme": "SBI Small Cap Fund - Regular Plan - Growth",
"value": 92000,
"held_with": "ARN-45678"
}
]
Two schemes, two different distributors, ₹2.77 lakh in AUM you didn’t know was there. Multiply that across a 50-client book and you’re looking at real money.
Getting a fresh CAS without chasing the client for one
None of this works without a recent, complete CAS, and most clients don’t have one lying around. CAS Generator handles the input side of the problem, end to end, without anyone downloading or re-uploading a PDF:
Steps 1 and 2 are CAS Generator’s job. POST /v4/generate requests a detailed CAS covering both CAMS- and KFintech-serviced AMCs in one call, since the two RTAs share data. It’s emailed to the client’s registered address, not returned in the API response, so step 3 needs something on the other end to catch it.
requests.post(
"https://api.casparser.in/v4/generate",
headers={"x-api-key": API_KEY},
json={
"email": client_email,
"from_date": "2015-01-01",
"to_date": "2026-12-31", # end of current year
"password": pdf_password,
},
)
# Lands in the client's inbox within 1-2 minutes.
If the client is already set up with an inbound-email alias or Gmail import from onboarding (covered in CAS-first architecture for wealth-tech), the generated CAS gets captured and parsed the moment it arrives. Three API calls, generate, capture, parse, and you’re diffing ARN codes without anyone touching a PDF by hand.
What this actually lets you do
It tells you where the AUM sits. Moving it runs through AMFI’s process, not through any API.
AMFI’s formal term for this is a “Change of Distributor.” Distributor platforms and investors tend to call it “Change of Broker,” or COB. Under SEBI’s December 2009 circular, an investor can move a folio to a new ARN without a No Objection Certificate from the current distributor. The process uses a one-page form per AMC (AMFI’s “Request for Change in Mutual Fund Distributor,” Annexure A) with old ARN, new ARN, folio number, scheme name, and the investor’s signature.
That form doesn’t cover everything your comparison list flags, and mixing these up is the easiest way to send someone the wrong pitch:
| Holding type | Covered by the ARN change form? | What actually moves it |
|---|---|---|
| Regular Plan, SOA (statement) mode | Yes | Annexure A, filed per AMC |
| Mutual funds held in demat | No | A DP-to-DP transfer of units |
| Direct Plan | No | Nothing to move — no distributor is attached |
Both the demat case and the direct case will show up in held_elsewhere next to your actual competitor-held assets, but they need entirely different next steps. And even on a clean ARN change, commission on the transferred assets starts from the date the transfer processes. It isn’t backdated.
Try it with a sandbox key
You don’t need credits to test the ARN comparison logic. Use the sandbox key sandbox-with-json-responses and the API returns a sample parsed CAS — enough to verify your filter works before running it on real client data.
- Sandbox key:
sandbox-with-json-responses - Free plan: 10 credits/month, no credit card required
- Documentation: casparser.in/docs
Related reading: