Submit KYC you've already collected
If your app has already done KYC for a user, send it to us in one call instead of making them repeat it. We check it, our team reviews it, and you get a webhook when it is approved or rejected.
403 PARTNER_KYC_NOT_ENABLED. On the hosted embed, use the kyc field on /partner/users/init instead.This is the shortcut alternative to the step-by-step KYC endpoints (email, PAN, Aadhaar OTP). Use it when you already hold the user's verified PAN and Aadhaar record, for example from DigiLocker or an Aadhaar OKYC provider. Register the user first with POST /partner/users/init (flow: "api") to get their user_code.
1. Send the KYC
/partner/users/:user_code/kyc/submitkycSend the fields at the top level of the body, or wrapped as { "kyc": { … } } (the same object as the embed's kyc).
| Field | Type | Description | |
|---|---|---|---|
| pan | string | required | Individual PAN, e.g. ABCPK1234Z (the 4th character must be P). Case doesn't matter. |
| aadhaar | string | required | The full 12-digit Aadhaar number, or masked as "XXXXXXXX1234" (X, x or *; spaces and dashes are ignored). |
| aadhaar_data | object | required | The Aadhaar record your OKYC / DigiLocker provider returned, as JSON (keys below). Leave out the photo and the XML (64 KB limit). |
| dob | string | required | Date of birth as YYYY-MM-DD. Must match the record; the user must be 18 or older. |
| string | required | The user's email. | |
| pan_name | string | optional | The name on the PAN, if you have it. It must share a word with the Aadhaar name. |
| documents | object | optional | Optional images for our reviewer: pan_image, aadhaar_front, aadhaar_back. Each is base64, bare or as a data: URI, of a JPEG, PNG or PDF, up to 4 MB. Send any, all or none. |
Keys we read from aadhaar_data:
| 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 dob. |
| year_of_birth | If the record has only a year, it must match the year of dob. |
| masked_aadhaar · aadhaar_last4 · uid | If present, the last 4 digits must match 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 | Shown to our reviewer with the record. |
curl -X POST https://api.oropocket.com/partner/users/usr_xxx/kyc/submit \
-H "Authorization: Bearer oro_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"pan": "ABCPK1234Z",
"aadhaar": "XXXXXXXX4321",
"dob": "1990-08-15",
"email": "asha@example.com",
"pan_name": "ASHA KUMARI",
"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", "vtc": "Pune", "state": "Maharashtra", "pincode": "411001" }
},
"documents": {
"pan_image": "data:image/jpeg;base64,/9j/4AAQSk...",
"aadhaar_front": "data:image/png;base64,iVBORw0KG..."
}
}'The image type is read from the file itself, so a mislabelled data URI still works, and anything that isn't really a JPEG, PNG or PDF is refused. Keep the whole request under 10 MB.
2. The result
A KYC problem is a normal 200 response with status and a list of errors, so you can show the user what to fix.
{
"success": true,
"request_id": "req_xxx",
"mode": "live",
"data": {
"user_code": "usr_xxx",
"status": "pending_review",
"errors": [],
"persisted": true,
"documents_received": ["pan_image", "aadhaar_front"]
}
}| status | Meaning |
|---|---|
| pending_review | Checks passed and the KYC is saved for our team to review. persisted is true. Sending again while it is pending replaces it (replaced: true). |
| rejected | Something didn't pass. errors lists every problem; nothing was saved. |
| already_verified | The user's OroPocket KYC is already approved. Nothing was changed. |
| already_under_review | The user already has KYC waiting for review that you didn't send (their own, or from another app). Nothing was changed. |
| validated_sandbox | Sandbox key: the data and documents passed the format checks. Nothing is saved, and no duplicate check runs. |
| 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_MISMATCH · UNDER_18 | dob isn't a real date, differs from the record, or the user is under 18. |
| INVALID_EMAIL · EMAIL_IN_USE | No valid email, or it belongs to a different OroPocket account. |
| NAME_MISMATCH | pan_name and the Aadhaar name share no word. |
| PAN_IN_USE · AADHAAR_IN_USE | Already on a different OroPocket account. |
| INVALID_DOCUMENT | A document isn't base64 of a JPEG, PNG or PDF, or has an unknown name. |
| DOCUMENT_TOO_LARGE | A document is over 4 MB. |
Error messages never repeat the values you sent. These refuse the request itself:
| Code | Meaning |
|---|---|
| 403 PARTNER_KYC_NOT_ENABLED | Accept partner KYC via raw API isn't on for your account. |
| 403 API_NOT_ALLOWED | Your key doesn't have the kyc capability. |
| 404 USER_CODE_NOT_FOUND | The user_code isn't one of your users. |
3. Review and webhooks
Our team reviews each submission against the Aadhaar record and any images, usually within a working day. While it is pending, GET /partner/users/:user_code/kyc/status returns status: "under_review" and source: "partner", and anything that needs approved KYC (such as INR withdrawals) stays blocked. When it has been reviewed we send a webhook:
kyc.approved: the user's KYC is approved.kyc.rejected, with thereason. The PAN and Aadhaar are released and the images deleted, so you can submit corrected details, or the user can complete KYC in the app.
{
"event": "kyc.rejected",
"event_id": "evt_xxx",
"created_at": "2026-10-14T10:12:00.000Z",
"data": {
"user_code": "usr_xxx",
"status": "rejected",
"reason": "The name on the PAN does not match the Aadhaar record."
}
}4. How we handle the data
- The KYC is recorded as submitted by you, with your account against it, and is only approved by our team.
- 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 inside aadhaar_data are dropped.
- Document images are stored privately and seen only by our reviewers. They are never at a public URL, and are deleted if the KYC is rejected.
- 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.