Resident eKYC SDK
HTTP API + DigiLocker OAuth integration for Resident DigiLocker (/kyc/) and KFin KRA (/kyc/kfin). No native DigiLocker binary SDK — Flutter and React use REST + browser redirect.
Product docs eKYC hub Health API1. Overview
| Capability | Status |
|---|---|
| Flutter (Android / iOS) | Supported — REST + system browser / Custom Tabs |
| React / Next.js / Vue | Supported — fetch + redirect |
| Native DigiLocker package | Not required — MeriPehchaan hosted OAuth |
| DigiLocker secrets in client app | Never — stay on PredictRAM Auth Partner |
2. Base URL
https://web.predictram.com
Local: your Flask host (e.g. http://127.0.0.1:5010). Always send Accept: application/json on API calls.
3. DigiLocker resident sequence
POST /api/kyc/v1/sessions → session_id
GET .../sessions/{id}/digilocker/start → 302 DigiLocker
(user consents on MeriPehchaan)
GET /api/kyc/v1/digilocker/callback → digilocker_verified
GET /api/kyc/v1/sessions/{id} → poll status / ekyc summary
→ /kyc/session/{id}/onboarding
POST .../aadhaar/otp/send|verify
POST .../ipv
POST .../declarations
POST .../signature
POST .../pack/build → PDF + All-KRA ZIP
GET .../pack/download
GET .../kra-pack/download
POST .../kra-pack/push → KFin SFTP (if configured)
4. DigiLocker API reference
| Method | Endpoint | Purpose |
|---|---|---|
| GET | /api/kyc/v1/health | DigiLocker config health |
| POST | /api/kyc/v1/sessions | Create resident session |
| GET | /api/kyc/v1/sessions/{id} | Session + ekyc summary |
| GET | /api/kyc/v1/sessions/{id}/digilocker/start | Start DigiLocker OAuth |
| GET | /api/kyc/v1/digilocker/callback | OAuth callback (hosted) |
| POST | /api/kyc/v1/sessions/{id}/aadhaar/otp/send | Onboarding Aadhaar OTP |
| POST | /api/kyc/v1/sessions/{id}/aadhaar/otp/verify | Verify OTP |
| POST | /api/kyc/v1/sessions/{id}/ipv | IPV selfie (+ optional geo) |
| POST | /api/kyc/v1/sessions/{id}/declarations | RA / FATCA / PEP decls |
| POST | /api/kyc/v1/sessions/{id}/signature | Wet / click-wrap signature |
| POST | /api/kyc/v1/sessions/{id}/pack/build | PDF + All-KRA packs |
| GET | /api/kyc/v1/sessions/{id}/pack/download | Download merged PDF |
| GET | /api/kyc/v1/sessions/{id}/kra-pack/download | Download All-KRA ZIP |
| POST | /api/kyc/v1/sessions/{id}/kra-pack/push | SFTP push KFin batch |
Create DigiLocker session
POST /api/kyc/v1/sessions
Content-Type: application/json
{
"journey_type": "resident",
"external_client_ref": "your-user-id",
"tenant_id": "your-firm",
"pan": "ABCDE1234F",
"pan_consent": true
}
Typical statuses
created → awaiting_digilocker → digilocker_verified
→ (onboarding) → kyc_pack_ready → kyc_kra_pushed | failed
5. KFin resident sequence
POST /api/kyc/v1/kfin/sessions
POST .../contact/otp/send + verify (mobile + email)
GET|POST .../digilocker/start (PANCR + e-Aadhaar)
POST .../aadhaar (Offline XML/ZIP fallback)
POST .../details (MITC + IPV + signature)
POST .../pack/build (KFin ZIP + All-KRA ZIP)
GET .../pack/download
GET .../pack/download-all-kra
POST .../push (SFTP or demo UNDER_PROCESS)
GET .../checklist
6. KFin API reference
| Method | Endpoint | Purpose |
|---|---|---|
| POST | /api/kyc/v1/kfin/sessions | Create KFin session (PAN) |
| GET | /api/kyc/v1/kfin/sessions/{id} | Session + checklist |
| POST | /api/kyc/v1/kfin/sessions/{id}/contact/otp/send | Send mobile/email OTP |
| POST | /api/kyc/v1/kfin/sessions/{id}/contact/otp/verify | Verify contact OTP |
| GET/POST | /api/kyc/v1/kfin/sessions/{id}/digilocker/start | Bridge DigiLocker into KFin |
| POST | /api/kyc/v1/kfin/sessions/{id}/aadhaar | Offline Aadhaar XML/ZIP |
| POST | /api/kyc/v1/kfin/sessions/{id}/details | MITC + IPV + signature |
| GET | /api/kyc/v1/kfin/sessions/{id}/checklist | Ready-to-push checklist |
| POST | /api/kyc/v1/kfin/sessions/{id}/pack/build | Build KFin + All-KRA |
| GET | /api/kyc/v1/kfin/sessions/{id}/pack/download | KFin official ZIP |
| GET | /api/kyc/v1/kfin/sessions/{id}/pack/download-all-kra | All-KRA ZIP |
| POST | /api/kyc/v1/kfin/sessions/{id}/push | SFTP push ({"demo":true} optional) |
Create KFin session
POST /api/kyc/v1/kfin/sessions
Content-Type: application/json
{
"pan": "ABCDE1234F",
"name": "OPTIONAL NAME",
"mobile": "9876543210",
"email": "client@example.com"
}
7. All-KRA pack contents
ALL_KRA_{PAN}_{YYYYMMDD}.zip
README.txt
MANIFEST.json
01_KFIN/ — official KFin batch ZIP (SFTP-ready)
02_CVL/ — CVL_KYC_DATA.txt (tilde, no header)
03_CAMS/ — portable CSV + JSON
04_NDML/ — portable CSV + JSON
05_DOTEX/ — portable CSV + JSON
SHARED/ — DL_Aadh.xml / IPV when available
8. Flutter sample (DigiLocker)
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:url_launcher/url_launcher.dart';
const base = 'https://web.predictram.com';
Future<String> startResidentDigilocker({String? pan}) async {
final create = await http.post(
Uri.parse('$base/api/kyc/v1/sessions'),
headers: {'Content-Type': 'application/json', 'Accept': 'application/json'},
body: jsonEncode({
'journey_type': 'resident',
'external_client_ref': 'flutter-user-1',
if (pan != null) 'pan': pan,
'pan_consent': pan != null,
}),
);
final data = jsonDecode(create.body) as Map<String, dynamic>;
if (data['success'] != true) {
throw Exception(data['error'] ?? 'session failed');
}
final sessionId = data['session']['id'] as String;
await launchUrl(
Uri.parse('$base/api/kyc/v1/sessions/$sessionId/digilocker/start'),
mode: LaunchMode.externalApplication,
);
return sessionId;
}
Future<Map<String, dynamic>> getSession(String id) async {
final res = await http.get(Uri.parse('$base/api/kyc/v1/sessions/$id'));
return jsonDecode(res.body) as Map<String, dynamic>;
}
Prefer system browser / Custom Tabs for DigiLocker (not an insecure WebView).
After
digilocker_verified, open onboarding or call pack APIs from your backend.
9. React / Web sample (DigiLocker + KFin)
const BASE = 'https://web.predictram.com';
export async function startDigilockerResident({ pan, externalClientRef }) {
const res = await fetch(`${BASE}/api/kyc/v1/sessions`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
body: JSON.stringify({
journey_type: 'resident',
external_client_ref: externalClientRef,
pan,
pan_consent: !!pan,
}),
});
const data = await res.json();
if (!data.success) throw new Error(data.error || 'session failed');
window.location.href =
`${BASE}/api/kyc/v1/sessions/${data.session.id}/digilocker/start`;
return data.session.id;
}
export async function startKfinSession({ pan, mobile, email }) {
const res = await fetch(`${BASE}/api/kyc/v1/kfin/sessions`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
body: JSON.stringify({ pan, mobile, email }),
});
const data = await res.json();
if (!data.success) throw new Error(data.error || 'kfin session failed');
// Continue in PredictRAM UI, or drive steps via KFin APIs:
window.location.href = data.continue_url || `${BASE}/kyc/kfin/session/${data.session_id}`;
return data.session_id;
}
export async function buildAndDownloadAllKra(sessionId, { kfin = false } = {}) {
const buildPath = kfin
? `${BASE}/api/kyc/v1/kfin/sessions/${sessionId}/pack/build`
: `${BASE}/api/kyc/v1/sessions/${sessionId}/pack/build`;
const built = await fetch(buildPath, { method: 'POST', headers: { Accept: 'application/json' } });
const data = await built.json();
if (!data.success) throw new Error(data.error || 'pack build failed');
const dl = kfin
? (data.all_kra_download_url || data.download_url)
: (data.kra_download_url || data.download_url);
if (dl) window.location.href = dl.startsWith('http') ? dl : `${BASE}${dl}`;
return data;
}
10. Errors & tips
- JSON errors return
{"success": false, "error": "..."}with HTTP 4xx/5xx. - KFin official batch needs UIDAI-signed Aadhaar XML (DigiLocker e-Aadhaar or Offline ZIP).
- SFTP push requires credentials at /admin/kyc-kfin; otherwise use download or demo push.
- Do not embed DigiLocker Client Secret in mobile/web clients.
Related
Product documentation · eKYC hub · UI demo · Live DigiLocker · Live KFin