Email_Parsing_V1 — Unlocked CAS Statements from Gmail

Email_Parsing_V1 v1 live

Download as Markdownthe full page as a single .md file — for offline reading or as context for an AI assistant

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

GET /email-parsing/v1/documents/:token
URLhttps://api.pehchaantech.com/email-parsing/v1/documents/:token
Timeout45000 ms
Rate limit60 req/min · 100000 req/day
GET /email-parsing/v1/sessions/:ref
URLhttps://api.pehchaantech.com/email-parsing/v1/sessions/:ref
Timeout10000 ms
Rate limit60 req/min · 100000 req/day
GET /email-parsing/v1/sessions/:ref/documents
URLhttps://api.pehchaantech.com/email-parsing/v1/sessions/:ref/documents
Timeout10000 ms
Rate limit60 req/min · 100000 req/day
POST /email-parsing/v1/connect
URLhttps://api.pehchaantech.com/email-parsing/v1/connect
Timeout20000 ms
Rate limit60 req/min · 100000 req/day
POST /email-parsing/v1/sessions/:ref/disconnect
URLhttps://api.pehchaantech.com/email-parsing/v1/sessions/:ref/disconnect
Timeout20000 ms
Rate limit60 req/min · 100000 req/day
POST /email-parsing/v1/sessions/:ref/documents/:doc_ref/unlock
URLhttps://api.pehchaantech.com/email-parsing/v1/sessions/:ref/documents/:doc_ref/unlock
Timeout45000 ms
Rate limit60 req/min · 100000 req/day

Overview

Get your customer’s consolidated account statements out of their Gmail, with the password taken off. The customer grants read access to their mailbox once, in their own browser; you get back the unlocked PDF and — where we can read it — the holdings as JSON.

THE DELIVERABLE IS THE UNLOCKED STATEMENT. NSDL and CDSL statements are encrypted with the investor’s PAN; CAMS and KFintech statements use a password the customer chose when they requested the statement. We derive the password where it is derivable, open the document, and hand you a short-lived link to the decrypted PDF.

THE PARSED JSON IS BEST EFFORT ON TOP OF THAT. Most statements parse. Some do not — a re-printed copy, a scan, a format we do not recognise. When that happens you still get a 200, still get the PDF, and get an explicit json_unavailable_reason saying which kind of unreadable it was. You do not lose the thing you paid for because we could not read it, so branch on ok rather than treating it as a failed call.

THIS IS NOT A SINGLE-CALL API. A real person has to grant Gmail access in the middle, on a page you do not control. Connect, send the customer to the start_url we return, poll the session until the mailbox scan finishes, list what we found, then unlock the statement you want — with a browser journey between the first call and the rest.

ONLY unlock IS BILLED. Connecting, polling the session, listing documents, redeeming a download link and disconnecting are all free.

THE MOST IMPORTANT THING IN THIS API IS scan_complete. A session in state discovering with zero documents and one in state no_documents with zero documents look almost identical, and they mean opposite things: the first is “we have not finished looking”, the second is “we looked, and this customer has no statements”. Branch on scan_complete, never on the document count. Telling a customer they hold no investments because you polled too early is the failure this field exists to prevent.

IDENTITY IS REQUIRED AT CONNECT, NOT AT UNLOCK. That is the one moment you have the customer’s details in front of you, and the document that will need them does not exist yet. A session started without a usable identity is one that fails minutes later, after a real person has already sat through a consent screen — so we refuse it up front instead. Send a PAN if you have one: for NSDL and CDSL it IS the password.

YOUR REDIRECT HOST MUST BE REGISTERED BEFORE IT IS ACCEPTED. This is a separate step from being granted the API — being able to authenticate is not the same as us being willing to send a customer’s browser somewhere. If /connect returns 401 unknown_tenant on a key that otherwise works, that is why: send us the hosts you will redirect to.

Only request this with the customer’s consent — a consolidated account statement is personal financial data, and the unlocked document contains the investor’s name, PAN, address and every holding. Set your client timeout to at least 40 seconds on unlock, which does a real download, decrypt and parse.

Request example

{
  "identity": {
    "pan": "ABCDE1234F",
    "date_of_birth": "1990-04-17"
  },
  "external_user_ref": "CUST_00123",
  "partner_redirect_uri": "https://your-app.example.com/cas/return"
}

Response example

{
  "ref": "ref_2b6fecc450f75beadd586f44be3b6610fd03db1e374044b4",
  "start_url": "https://api.pehchaantech.com/connect/v1/start/InJlZl8yYjZmZWNjNDUw"
}

Fields

FieldDescription
partner_redirect_uriRequired. Absolute https URL where the customer lands once consent finishes. The HOST must be registered for your organisation first — an unregistered one is refused, because this is a URL we will send a real customer’s browser to. URLs with embedded credentials are rejected outright. We append exactly one query parameter on the way back, `ref`, and nothing else: no token, no filename, no email address, because this URL lands in browser history and your logs.
external_user_refRequired. Your own identifier for the customer, 1–256 characters. Echoed nowhere and used only to tie a session to your records.
identityRequired, and must be USABLE rather than merely present. At least one derivable combination is needed: `pan`, or `mobile`, or `date_of_birth` together with `full_name`. A name on its own derives no password candidate and is refused with 422 — accepting it would be the same silent failure wearing a filled-in field. None of these values are stored, logged or returned; they are converted to password candidates on the spot and held in memory for one journey only.
identity.panThe single most useful field. 5 letters, 4 digits, 1 letter. For NSDL and CDSL statements the PAN IS the password, so with it the common case needs no further input from anyone. Not stored by this API.
identity.date_of_birthISO format, YYYY-MM-DD — for example 1990-04-17. Combined with `full_name` it derives the candidates some registrars use.
identity.full_nameThe investor’s name as registered with the registrar. Derives nothing on its own — it needs `date_of_birth` alongside it.
identity.mobile10 digits. A weaker signal than PAN but enough on its own to derive a candidate for some registrars.
refReturned. The session handle, and the only identifier you need from here on: session polling, the document list, unlock and disconnect are all keyed on it. Also the single query parameter we append to your redirect URI when the customer returns.
start_urlReturned. Send the customer’s BROWSER here — it is ours, on our domain, not the vendor’s consent URL. Single-purpose and time-boxed to 15 minutes, and it stops working the moment consent completes. Whoever opens it can attach THEIR mailbox to this session, so treat it like a one-time login link: send it to the customer, do not log it, do not render it anywhere a third party can read.

Changelog