A unity user is created before initiating the loan application journey. The API accepts a bunch of optional values like contact & bank details, date of birth, etc. that can be passed at the time of Unity User creation. These values will be later pre-populated in the LAMF journey for the user and improve the user experience.
Create a Unity user before starting a loan application. One Unity user can hold both an LAMF (mutual fund) and an LAS (stocks) application — the same API is used for both, with different payloads.
Store theunityUserIdThe response returns a
unityUserId. Store it — you'll need it for Create Interaction and Update DLA Holdings, and it's the identifier you pass to Combined Credit Snapshot.
Authentication is the same as every other Unity backend API — see the Unity API authentication for the x-gateway-secret / x-gateway-authtoken headers.
Idempotency and repeated calls
Calling this API multiple times for the same user (same PAN or same auth contact) is safe:
- Existing user by PAN — returns the existing Unity user, lender, and referrer without creating a duplicate.
- Existing user by auth contact — returns an error if the phone is already linked to a different Unity user.
- Same-payload retries — no side effect — returns the existing user Id.
So you can call this whenever you need a Unity user ID (e.g. before starting the flow) without worrying about duplicates.
LAMF (Loan Against Mutual Funds)
Use this when the user will pledge mutual fund holdings.
| Field | Required | Notes |
|---|---|---|
pan | yes | User's PAN. |
authContact | yes | At least number; used for identity and linking. This is where the initial authentication OTP is triggered. |
productType | no | Defaults to lamf. |
assetType | no | Defaults to MUTUALFUND for LAMF. |
holdings | no | Array of MF holdings. If non-empty, holdingsLastFetchedAt is required. |
holdingsLastFetchedAt | conditional | Required when holdings is non-empty (ISO 8601 / RFC 3339). |
dob | no | DD-MM-YYYY or YYYY-MM-DD (normalised to DD-MM-YYYY). |
referrer | no | Defaults to your partner name. |
name, age, isNri, contacts, bankAccounts | no | Optional pre-fill attributes. |
Example request (LAMF):
{
"pan": "AIXOL9094G",
"authContact": { "number": "9876543210", "countryCode": "+91" },
"productType": "lamf",
"assetType": "MUTUALFUND",
"dob": "04-11-1999",
"name": "Vishal Pal",
"age": 35,
"isNri": false,
"holdings": [ // pass all values as received from the user's CAS via RTAs/MFC
{
"repository": "CAMS",
"amcCode": "PP",
"folio": "16615967",
"schemeCode": "001ZG",
"schemeName": "Parag Parikh Flexi Cap Fund",
"isin": "INF879O01027",
"schemeType": "EQUITY",
"units": 131.57,
"lockInUnits": 13.157,
"isDemat": false,
"dpId": "1208160062733129", // mandatory if isDemat is true
"modeOfHolding": "", // optional - defaults to single holding if not passed
"lienEligibleUnits": 120.33, // optional - if not passed, eligible units = units - lockInUnits. If passed, these are considered the eligible units for the loan
"contact": {
"phone": { "number": "9876543210", "countryCode": "+91" }, // required
"email": "[email protected]"
}
}
],
"holdingsLastFetchedAt": "2023-05-07T00:00:00Z"
}MF holdings are optional at creation — you can seed them here via holdings[] (with holdingsLastFetchedAt), let them be fetched during the journey, or push them later via Update DLA Holdings.
LAS (Loan Against Stocks)
Use this when the user will pledge stock holdings.
| Field | Required | Notes |
|---|---|---|
pan | yes | User's PAN. |
authContact | yes | At least number. |
assetType | yes | Must be STOCKS for LAS. |
stockHoldings | yes | Array of stock holdings. For LAS, only stockHoldings are used for eligibility — MF holdings are not required. |
productType | no | Defaults to lamf. |
dob | no | Same format as LAMF. |
referrer | no | Defaults to your partner name. |
name, age, isNri, contacts | no | Optional pre-fill attributes. |
Example request (LAS):
{
"pan": "EAWPK9000N",
"authContact": { "number": "9919921000", "countryCode": "+91" },
"assetType": "STOCKS",
"stockHoldings": [
{
"name": "TATA STEEL LIMITED",
"isin": "INE081A01020",
"type": "EQUITY",
"units": 100,
"isDemat": true,
"dpId": "1208160010814163"
}
],
"productType": "lamf",
"contacts": [
{ "type": "PHONE", "phone": { "number": "9919921000", "countryCode": "+91" } },
{ "type": "EMAIL", "email": "[email protected]" }
],
"name": "Vishal Pal",
"age": 55,
"isNri": false
}For STOCKS, every holding needs a dpId, and isDemat is always true.
Success response (HTTP 200)
{
"code": 0,
"data": {
"lender": "bajaj_finserv",
"referrer": "gatewaydemo-stag",
"unityUserId": "69a960a8fd4c213259f9a609"
},
"message": "SUCCESS"
}data.unityUserId is the identifier to store and reuse across the rest of the integration.
Error responses
All errors follow the same shape:
{
"message": "<error_message>",
"code": "<error_code>",
"data": "<optional_data>"
}| HTTP status | code | message / scenario |
|---|---|---|
| 400 | 4000 | invalid_request — invalid JSON, invalid payload, invalid DOB format, or holdings present but holdingsLastFetchedAt missing. |
| 400 | 4000 | invalid_request:auth_contact_required — authContact missing or number empty. |
| 400 | 4303 | invalid_product_type — product type or asset type not allowed for the partner. |
| 400 | 4309 | invalid_asset_type — invalid asset type. |
| 400 | 4209 | invalid_pan — non-individual PAN. |
| 400 | 3003 | Name is required. |
| 400 | 3004 | Age or DOB is required. |
| 400 | 3006 | IsNRI is required. |
| 400 | 4406 | not_eligible_wrt_age_limit. |
| 400 | 4407 | not_eligible_wrt_nri_status. |
| 400 | 4408 | no_eligible_lender_found. |
| 401 | 4001 | partner_inactive. |
| 403 | 3002 | Phone already used — auth contact already linked to another Unity user. |
| 500 | 2000 | internal_server_error. |
| 200 | 0 | SUCCESS with an error key referrer_already_mapped — user already exists with a different referrer; data still contains unityUserId, referrer, lender (backward-compatible success with a warning). |
Exact message and code values are defined by the Unity API contract; the table above summarises the main scenarios partners may see.
Testing with a mock user (Disabled Lien Marking)To trial the flow without real lien marking, set
isLienMarkingMocked: trueto create a Disabled Lien Marking (DLM) user. The journey behaves identically except at the lien-marking step: the RTA request is still made, but any OTP is accepted and the RTA response is mocked, so no real OTP is ever sent. Not available for the SIB lender —isLienMarkingMockedstaysfalsethere regardless of what you pass. Don't set this flag for production users.