Advanced embed configuration
Two switches for partners whose users are already verified in the partner's own app: skip OroPocket's OTP, and hand over the user's KYC so they never repeat it.
By default, the first time a user opens the hosted embed through your app, OroPocket sends them an OTP, and buying beyond the basics needs our KYC. If your app has already verified the mobile number and done KYC (for example through DigiLocker or an Aadhaar OKYC provider), you can skip both.
1. Skip the OTP
With Skip OTP on embed login on, the embed_url you get from /partner/users/init opens straight into the user's account. There is no OTP screen, and nothing changes in your call.
- New users get an OroPocket account created on that first open, linked to you.
- People who already use OroPocket are logged in too. Inside your embed they see only what they hold through you (their sub-wallet), never what they hold elsewhere.
- Use a fresh link every time. Each
embed_urlworks once and for 10 minutes. If you build the URL yourself from a user's permanentuser_code, the user is still asked for an OTP: a permanent code can leak through browser history or logs, so it is never treated as a login. - Suspended accounts are refused exactly as before.
- Sandbox. With an
oro_test_key the OTP is skipped too, so you can test the flow end to end.
2. Send the user's KYC
/partner/users/initembedWith Accept partner KYC at user init on, add a kyc object to the same call. We check it on our side (no second verification for the user) and, if it passes, their OroPocket KYC is approved before they open the embed. Their name, date of birth and email are taken from it, so they also skip the profile screen.
| Field | Type | Description | |
|---|---|---|---|
| kyc | object | optional | The user's KYC, as verified in your app. Only on the embed flow (flow "embed"). |
| kyc.pan | string | required | Individual PAN, e.g. ABCPK1234Z (the 4th character must be P). Case doesn't matter. |
| kyc.aadhaar | string | required | The full 12-digit Aadhaar number, or the masked form "XXXXXXXX1234" (X, x or *; spaces and dashes are ignored). Send masked if that is all you are allowed to keep. |
| kyc.aadhaar_data | object | required | The Aadhaar record your OKYC / DigiLocker provider returned, as JSON. Keys we read are listed below; others are ignored. Leave out the photo and the XML (64 KB limit). |
| kyc.dob | string | required | Date of birth as YYYY-MM-DD. Must match the record, and the user must be 18 or older. |
| kyc.email | string | optional | The user's email. Falls back to the top-level email; one of the two is required. |
| kyc.pan_name | string | optional | The name on the PAN, if you have it. It must share a word with the Aadhaar name. |
Keys we read from aadhaar_data (the usual OKYC and DigiLocker spellings both work):
| Key | Use |
|---|---|
| name (required) | The legal name. It becomes the user's name on OroPocket, their invoices and their holding certificate. |
| dob · date_of_birth · dateOfBirth | DD-MM-YYYY, DD/MM/YYYY or YYYY-MM-DD. Must equal kyc.dob. |
| year_of_birth | If the record has only a year, it must match the year of kyc.dob. |
| masked_aadhaar · aadhaar_last4 · uid | If present, the last 4 digits must match kyc.aadhaar. |
| address (object) · split_address | house, street, landmark, vtc, district, state, pincode. |
| full_address · address (string) | Kept as the full address. |
| gender · care_of · reference_id | Kept with the record. |
curl -X POST https://api.oropocket.com/partner/users/init \
-H "Authorization: Bearer oro_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"flow": "embed",
"mobile": "9876543210",
"name": "Asha Kumari",
"email": "asha@example.com",
"kyc": {
"pan": "ABCPK1234Z",
"aadhaar": "XXXXXXXX4321",
"dob": "1990-08-15",
"email": "asha@example.com",
"aadhaar_data": {
"name": "Asha Kumari",
"dob": "15-08-1990",
"gender": "F",
"care_of": "D/O Ram Kumar",
"masked_aadhaar": "xxxxxxxx4321",
"reference_id": "your-okyc-reference",
"address": {
"house": "12", "street": "MG Road", "landmark": "Near the park",
"vtc": "Pune", "district": "Pune", "state": "Maharashtra", "pincode": "411001"
}
}
}
}'3. The kyc result
A KYC problem never stops the login. You always get the embed_url, plus a kyc block telling you what happened. If KYC was not approved, the user can complete it in the embed later, the normal way.
{
"success": true,
"request_id": "req_xxx",
"mode": "live",
"data": {
"user_code": "usr_xxx",
"embed_url": "https://connect.oropocket.com/?u=usr_yyy",
"expires_at": "2026-10-13T09:22:00.000Z",
"expires_in_seconds": 600,
"user_existed": false,
"mode": "live",
"kyc": { "status": "approved", "errors": [], "persisted": true }
}
}| kyc.status | Meaning |
|---|---|
| approved | Checks passed and the user's KYC is approved. persisted is true. |
| already_verified | The user had already completed OroPocket KYC. Nothing was changed. |
| rejected | Something didn't pass. errors lists every problem; nothing was saved. |
| validated_sandbox | Sandbox key: the data passed the format checks, but nothing is saved and no duplicate check runs. |
"kyc": {
"status": "rejected",
"persisted": false,
"errors": [
{ "code": "DOB_MISMATCH", "field": "kyc.dob", "message": "dob does not match aadhaar_data." }
]
}| Error code | Meaning |
|---|---|
| INVALID_PAN | Not a PAN, or not an individual's PAN. |
| INVALID_AADHAAR | Not 12 digits, fails the Aadhaar checksum, or not in the masked form. |
| AADHAAR_LAST4_MISMATCH | The last 4 digits differ from the ones in aadhaar_data. |
| INVALID_AADHAAR_DATA | aadhaar_data is missing, has no name or date of birth, or is over 64 KB. |
| INVALID_DOB | dob isn't a real YYYY-MM-DD date. |
| DOB_MISMATCH | dob differs from the date (or year) of birth in aadhaar_data. |
| UNDER_18 | The user is under 18. |
| INVALID_EMAIL | No email, or not a valid one. |
| NAME_MISMATCH | pan_name and the Aadhaar name share no word. |
| PAN_IN_USE · AADHAAR_IN_USE | Already verified on a different OroPocket account. |
| EMAIL_IN_USE | The email belongs to a different OroPocket account. |
| USER_SUSPENDED | The account for this mobile is suspended. |
| KYC_NOT_RECORDED | We couldn't save it just now. Retry the init, or let the user complete KYC in the app. |
Error messages never repeat the values you sent. You can check a user's KYC at any time with GET /partner/users/:user_code/kyc/status (see KYC).
4. Request errors
These refuse the whole request, like any other contract error. No link is issued.
| Code | Meaning |
|---|---|
| 403 PARTNER_KYC_NOT_ENABLED | You sent kyc but Accept partner KYC at user init isn't on for your account. Leave kyc out, or ask OroPocket. |
| 400 INVALID_KYC_FLOW | kyc was sent on the trusted-API flow (flow "api"). It only applies to the hosted embed. |
5. How we handle the data
- The KYC is recorded as attested by you, separately from KYC we verified ourselves, with your account against it.
- We keep the PAN, the Aadhaar number (only the last 4 digits when you send it masked), the name, date of birth, gender, address and email. Photos, XML, signatures and share codes are dropped and never stored.
- Request bodies are never written to your request logs, and our own logs carry masked values only.
- Send only KYC you have actually verified, with the user's consent to share it with OroPocket.
Related: Open the embed on a screen (use launch in the same call) and WebView & UPI setup.