# MF_Pledge_V1 — Mutual Fund Pledge & Loan Eligibility API

**MF_Pledge_V1** · version `v1` · status `live`

## Authentication

Every request must carry your API key in the `X-API-Key` header. Your key is
issued to you separately by ops and is never shown in this document.

```
X-API-Key: <your-key>
```

## Base URL

All endpoints are served through the gateway:

```
https://api.pehchaantech.com
```

## Endpoints

| Method | Path | Full URL | Timeout |
| --- | --- | --- | --- |
| `POST` | `/mf-pledge/v1/link` | `https://api.pehchaantech.com/mf-pledge/v1/link` | 35000 ms |
| `POST` | `/mf-pledge/v1/portfolio` | `https://api.pehchaantech.com/mf-pledge/v1/portfolio` | 35000 ms |
| `POST` | `/mf-pledge/v1/status` | `https://api.pehchaantech.com/mf-pledge/v1/status` | 10000 ms |

Rate limit: **60 requests/minute** · **100000 requests/day**, counted per API key.

## Overview

Find out what mutual funds a customer holds and how much each lender will lend against them. The customer authorises the lookup once, in their own browser, and you get back a normalised portfolio with per-lender eligibility.

THIS IS NOT A SINGLE-CALL API. A real person has to authorise the lookup in the middle, on a page you do not control. Create a link, send the customer to it, and read the portfolio once they are done — three calls with a browser journey between the first and the last.

ONLY THE FIRST CALL IS BILLED. Creating a link sends the customer a one-time password and costs money; checking status and reading the portfolio are both free. Creating a link is therefore NOT idempotent: ask twice for the same customer and you get the first link back rather than a new one, because a second link would send another OTP and invalidate the one already in their hand.

THE MOST IMPORTANT THING IN THIS API IS THE `evidence` BLOCK. An empty portfolio does not mean the customer owns nothing — it looks identical whether they genuinely hold no mutual funds, abandoned the journey, or finished and closed the tab. `evidence` tells you which of those we actually observed, and says so honestly when we do not know. Never tell a customer they hold nothing on an empty portfolio alone; check `evidence.fetchConfirmed` first.

Only request this with the customer’s consent — a mutual fund portfolio is personal financial data. Latency is capped at 30 seconds, so set your client timeout to at least 35 seconds.

## Request example

```json
{
  "pan": "ABCDE1234F",
  "mobile": "9015484311",
  "redirect_url": "https://your-app.example.com/mf/return",
  "internal_customer_id": "CUST_00123"
}
```

## Response example

```json
{
  "status": "completed",
  "link_id": "9c1f8b2e-1d44-4a0e-9f7c-2b6a1d3e5f08",
  "success": true,
  "evidence": {
    "note": "customer completed the vendor journey",
    "fetchConfirmed": true,
    "customerReturned": true
  },
  "portfolio": {
    "name": "ANSHKUMAR",
    "lenders": [
      {
        "code": "BAJAJ_FINSERV_LTD",
        "available": true,
        "eligibilityAmount": 1012
      },
      {
        "code": "CUB",
        "available": false,
        "eligibilityAmount": 0
      },
      {
        "code": "SURYODAY",
        "available": true,
        "eligibilityAmount": 500
      },
      {
        "code": "PIRAMAL_FINANCE",
        "available": false,
        "eligibilityAmount": 0
      }
    ],
    "holdings": [
      {
        "nav": 9.2989,
        "isin": "INF846K010S6",
        "folio": "910221306865",
        "amcName": "Axis Mutual Fund",
        "assetType": "EQUITY",
        "schemeName": "AXIS NIFTY IT INDEX FUND Regular Growth",
        "totalUnits": 9.517,
        "pledgedUnits": 0,
        "totalMarketValue": 88.5,
        "availablePledgeUnits": 9.517,
        "pledgableMarketValue": 88.51
      }
    ],
    "hasPledge": false,
    "totalMutualFunds": 18,
    "totalPortfolioAmount": 3722.68,
    "totalAvailablePledgeUnits": 9.51,
    "totalAvailablePledgeAmount": 3722.7
  }
}
```

## Fields

| Field | Description |
| --- | --- |
| `internal_customer_id` | Required. Your own identifier for the customer, 1–128 characters. Used to enforce one live link per customer, and to list a customer’s links. |
| `mobile` | Required. 10 digits starting 6–9. Must be the number registered against the customer’s mutual fund folios — the OTP goes there, and the lookup is keyed on it. |
| `pan` | Required. 5 letters, 4 digits, 1 letter. Used for the lookup and NOT stored by this API. |
| `redirect_url` | Required. Absolute https URL where the customer lands when the journey ends. We append a `ref` parameter identifying the journey. Treat the redirect as a hint, not proof — customers close tabs and deeplinks fail. Confirm with status or portfolio before acting on it. |
| `name (rejected)` | Deliberately NOT accepted — sending it is a 422. There is nowhere to forward a name, and a name DOES come back in the portfolio, resolved from the PAN rather than from you. Accepting one silently would invite exactly the wrong conclusion about where it came from. |
| `evidence` | On every status and portfolio response, alongside `portfolio` rather than inside it. `customerReturned` is whether they came back from the authorisation journey; `fetchConfirmed` is whether the source confirmed the lookup ran. Both true plus an empty portfolio means a REAL zero. Both false means unknown — do not tell the customer they hold nothing. |
| `lenders[]` | An array, never fixed fields, because lenders are onboarded over time. Treat an unfamiliar `code` as a new lender rather than an error, and never assume the array’s length or order. `available: false` with a zero amount is normal — the customer’s specific funds are not on that lender’s approved list. It is not a failure. |
| `amounts` | Passed through exactly as the source reports them, including floating point artifacts. Totals across different fields can disagree in the last decimal place, so do not build reconciliation that requires them to match. Round at your own presentation layer. |

## Errors

| Code | Meaning |
| --- | --- |
| `link_created (HTTP 201) — BILLABLE` | Link minted and an OTP sent to the customer. Send them to link_url and keep link_id. This is the only call that costs money. |
| `link_active (HTTP 200) — not billable` | A live link already exists for this customer, so it was returned instead of minting a second one. No OTP was sent. Deliberate: a second link would invalidate the one the customer is holding. |
| `completed (HTTP 200) — not billable` | Portfolio returned with holdings and lender eligibility. |
| `empty (HTTP 200) — not billable` | No holdings in the response. READ `evidence` BEFORE ACTING. With fetchConfirmed true this is a real zero and safe to tell the customer. With it false, the journey is unfinished and the customer may well own plenty — prompt them to complete it instead. |
| `not_found (HTTP 404) — not billable` | No such link_id for your account. |
| `validation (HTTP 422) — not billable` | Bad PAN or mobile, a non-https redirect_url, or an unknown field. Rejected before the upstream is called, so nothing was sent and nothing was charged. Retrying unchanged fails identically. |
| `failed (HTTP 502) — not billable` | Upstream unavailable or it rejected the request. Transient — retry with backoff. |

## Changelog

- **2026-07-28** — Initial release: three endpoints around a browser authorisation journey, one live link per customer, and an `evidence` block on every status and portfolio response so an empty portfolio is never mistaken for a customer who owns nothing. Only link creation is billed.

---

_Generated from the pehchaantech developer portal · canonical page: https://docs.pehchaantech.com/docs/mf-pledge-v1 · last updated: 2026-07-28T08:21:21.101Z._
