# PF_Details_V1 — EPF Passbook API

**PF_Details_V1** · version `v1` · status `deprecated`

> **Deprecated** — this API may be withdrawn in a future version. Plan your migration.

## 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` | `/pf-details/v1` | `https://api.pehchaantech.com/pf-details/v1` | 35000 ms |

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

## Overview

Retrieve an individual’s EPF (Provident Fund) details from their PAN: employer establishments, month-wise employee and employer contributions, and PF balances. One call returns the whole passbook — the platform handles EPFO connectivity and UAN matching behind the scenes.

PAN is the ONLY accepted identifier. Sending any other field (uan, mobile, month_range, epf_balance) is rejected with 422 by design, so nobody builds against a parameter the API would silently ignore. Note month_range specifically: the HISTORY WINDOW IS FIXED AT 12 MONTHS by the platform and is not a request field. Silently ignoring it would let you ask for 3 months, be billed for a 12-month lookup, and have nothing in the response to tell you which you got — so it is an explicit 422 instead.

Every response — success or not — uses the same envelope, so branch on the `status` field. Most calls resolve in one round trip, but the source can accept a search and answer later: that returns 202 `pending`, which is free and worth retrying shortly (cap it at 2–3 attempts). Latency is capped at 30 seconds, so set your client timeout to at least 35 seconds. Look up a PAN only with the individual’s consent — an EPF passbook is personal financial data.

EVERY CALL IS AN INDEPENDENT LOOKUP. There are no sessions and nothing to resume, so send a fresh client_ref_num on every attempt (or omit it and let the platform generate one) — including when retrying a `pending`. Reusing a ref neither resumes an earlier search nor de-duplicates a charge; it is a trace key only.

BILLING: every outcome except `pending` and `failed` is billable, including the ones that return no passbook. A not_found or no_data answer costs the same as a successful lookup — the charge is for querying EPFO, not for finding something. `failed` (502, the source never answered) and `pending` (202, not an answer yet) are free. So: validate PANs before calling (a malformed PAN is rejected with 422 before it reaches the source and costs nothing, but a well-formed PAN for the wrong person is a real, billed lookup), don’t loop on no_data, cap your pending retries — the 202 is free but each retry is a brand-new lookup and the one that finally answers is billed — and de-duplicate: two calls for the same PAN are two charges.

## Request example

```json
{
  "pan": "ABCDE1234F",
  "client_ref_num": "hr-onboard-7f3a2b"
}
```

## Response example

```json
{
  "result": {
    "est_details": [
      {
        "office": "K R PURAM (WHITEFIELD)",
        "doc_epf": "03-12-2024",
        "doc_eps": "03-12-2024",
        "doj_epf": "28-06-2022",
        "est_name": "EXAMPLE EMPLOYER PRIVATE LIMITED",
        "passbook": [
          {
            "cr_pen_bal": "0",
            "db_cr_flag": "C",
            "particular": "Cont. For Due-Month 082022",
            "tr_date_my": "01-08-2022",
            "wage_month": "072022",
            "approved_on": "12-08-2022",
            "cr_ee_share": "1800",
            "cr_er_share": "1800",
            "tr_approved": "03-12-2024"
          }
        ],
        "member_id": "PYKRP24601000000010034",
        "passbook_status": "Success"
      }
    ],
    "employee_details": {
      "dob": "1998-10-28",
      "uan": "101847123111",
      "member_name": "RAUNIT KUMAR"
    }
  },
  "status": "completed",
  "success": true,
  "description": "Record found successfully",
  "client_ref_num": "pehchaan-b5f08841d8f1"
}
```

## Fields

| Field | Description |
| --- | --- |
| `pan` | Required, and the ONLY accepted identifier. Permanent Account Number: 5 letters, 4 digits, 1 letter (^[A-Za-z]{5}[0-9]{4}[A-Za-z]$). Case-insensitive. |
| `client_ref_num` | Optional trace id; 6–64 chars of A-Z a-z 0-9 . _ -. Omit and the platform generates one. A TRACE KEY, NOT A SESSION KEY: use a FRESH value on every attempt, including retries of a `pending` (202) — reusing one neither resumes an earlier search nor de-duplicates a charge. Also returned in the X-Client-Ref-Num response header. |
| `success` | true only when a passbook was delivered. |
| `status` | Machine-readable outcome — branch on this (see Outcomes below). |
| `result` | The passbook — present only when status = completed, otherwise null. Contains employee_details (uan, member_name, dob) and est_details[] (one entry per employer, each with a month-wise passbook[] of cr_ee_share / cr_er_share / cr_pen_bal / db_cr_flag / wage_month / tr_approved). Treat it as an OPEN structure: fields come from the EPFO record, est_details can be empty, optional dates may be absent, and new fields may appear without notice. Read the paths you need defensively rather than validating against a fixed schema. Two specifics worth coding for: passbook[] covers the last 12 months and interleaves EPFO’s annual interest postings, which arrive with an empty tr_date_my and wage_month and a particular like "Int. Updated upto 31/03/2025" — so not every entry has a wage month; and there are NO balance totals — this API returns contribution transactions, not balances, so there is no pf_balance and no overall_pf_balance object. Derive a balance by summing passbook[] over the window if you need one. |

## Errors

| Code | Meaning |
| --- | --- |
| `completed (HTTP 200) — BILLABLE` | Passbook delivered in result — consume it. |
| `pending (HTTP 202) — not billable` | "Search in progress — not billed; retry shortly as a new request." The source accepted the search and is still working, so an attempt a few seconds later has a real chance of landing. Cap it at 2–3 attempts; if it is still pending, treat it as a failure. We are NOT holding your place: the retry starts a fresh search (send a fresh client_ref_num) and the attempt that finally answers is billed. |
| `not_found (HTTP 200) — BILLABLE` | "No data found" — no EPF record is linked to this PAN. Definitive; do NOT retry. Billed the same as a successful lookup. |
| `no_data (HTTP 200) — BILLABLE` | "No result available" — the source holds nothing usable, commonly because the member never activated their EPFO account or their records conflict. Definitive for now; a lookup much later may succeed if they activate it. Do NOT retry on a timer — every attempt is billed and returns the same answer. |
| `invalid_input (HTTP 200) — BILLABLE` | "Invalid input provided" — the identifier was rejected by the source. Re-check the PAN with the customer; do NOT retry unchanged. |
| `failed (HTTP 502) — not billable` | "Source down — please retry later." Temporary upstream issue, or the source was too slow to answer. Retry with exponential backoff (~2 s, max 3 tries) using a FRESH client_ref_num — nothing is resumable here. Free, because the source never answered. |
| `401 / 403` | Missing or invalid API key, or the key is not granted this API. |
| `422` | Validation failed — malformed PAN, or a field outside the contract (uan, mobile, month_range and epf_balance are all rejected deliberately). Never retry unchanged. |
| `429` | Rate limited — respect the Retry-After header. |
| `503 / 504` | Gateway protecting itself, or the call exceeded the 35 s budget — retry. |

## Changelog

- **2026-07-27** — Initial release: PAN-only lookup over a fixed 12-month history window, uniform response envelope, and a free pending (202) state for searches the source accepts but has not finished. Every call is an independent lookup — use a fresh client_ref_num per attempt.

---

_Generated from the pehchaantech developer portal · canonical page: https://docs.pehchaantech.com/docs/pf-details-v1 · last updated: 2026-07-27T11:45:38.700Z._
