Partner API

Luồng KYC

Upload giấy tờ qua presigned URL, submit payload KYC, rồi poll trạng thái. Endpoint virtual-account chỉ mở khi KYC của user được duyệt.

Luồng 3 bước

  1. Presign — POST /api/v2/partners/users/kyc/presigned-url với userId, fileName, mimeType trả về { url, objectKey }.
  2. Upload — PUT bytes của file lên url với Content-Type đúng mimeType đã khai báo. Object nằm dưới kyc/<internal-user-id>/.
  3. Submit — POST /api/v2/partners/users/kyc với thông tin profile và mảng images trỏ tới object đã upload.

1. Xin presigned URL

Request
POST /api/v2/partners/users/kyc/presigned-url
{
  "userId": "ext-user-001",
  "fileName": "passport-front.png",
  "mimeType": "image/png"
}
Response
{
  "success": true,
  "data": {
    "url": "https://<storage-host>/kyc/<internal-user-id>/<uuid>-passport-front.png?...",
    "objectKey": "kyc/<internal-user-id>/<uuid>-passport-front.png"
  }
}

mimeType hỗ trợ: image/png, image/jpeg, video/mp4, video/webm, video/quicktime. Tối đa 5 MB mỗi file.

2. Upload file

PUT binary
curl -X PUT "$PRESIGNED_URL" \
  -H "Content-Type: image/png" \
  --data-binary @passport-front.png
PUT này đi tới object storage, không phải API host — không cần header access-key. Lặp lại presign + upload cho từng giấy tờ.

3. Submit payload KYC

Request
POST /api/v2/partners/users/kyc
{
  "userId": "ext-user-001",
  "firstName": "VAN A",
  "lastName": "NGUYEN",
  "gender": "male",
  "nationalId": "001234567890",
  "cardIdType": "ID_CARD",
  "dateOfBirth": "1990-01-15",
  "address": "1 Nguyen Hue",
  "phoneNumber": "0982222222",
  "phoneCode": "+84",
  "city": "Ho Chi Minh City",
  "state": "Ho Chi Minh",
  "country": "Vietnam",
  "zipCode": "700000",
  "images": [
    { "url": "<objectKey front>", "type": "front_certificate" },
    { "url": "<objectKey back>",  "type": "back_certificate" },
    { "url": "<objectKey selfie>","type": "selfie_only" }
  ]
}
  • cardIdType: PASSPORT hoặc ID_CARD.
  • images: tối thiểu 3 phần tử, type không trùng nhau trong front_certificate, back_certificate, selfie_only, selfie_video.
  • url của mỗi ảnh nhận giá trị objectKey trả về từ bước presigned-url.
  • Trường liên hệ (email, phoneNumber) được đối chiếu với thông tin đã khai báo lúc tạo user.

Poll trạng thái

GET /api/v2/partners/users/kyc?userId=ext-user-001

Trả về KYC record của user, hoặc submission mới nhất kèm status review (pending, approved, rejected) và comments của reviewer.

Khi người này đã KYC-approved

nationalId là duy nhất trên Zenith. Nếu id đã thuộc một user được duyệt ở tài khoản khác, API so khớp ngày sinh và tên chuẩn hóa: khớp hoàn toàn thì liên kết ngay; lệch thì giữ pending chờ admin review thay vì tạo bản ghi trùng.