Overview
This API set is designed for ISV (Independent Software Vendor) customers: Party A initiates onboarding applications for its end customer (companies), and the OristaPay platform handles the full process including company search, compliance review, IDV, signing, and automatic wallet creation.
After completing onboarding, ISV customers receive companyCode and walletId, and can directly use the ISV Transaction API to perform transfers, payment collection, Payout, and other transactions on behalf of merchants. Transaction API fields remain unchanged — Party A simply passes walletId as normal, and OristaPay automatically enforces authorization based on the ISV ↔ merchant relationship.
The authentication, signing, request headers, response envelope, file upload, and error code system of this API set are fully consistent with the RDPAY API. For details not repeated in this document, please refer to the ISV Transaction API.
Business Flow
Identifier Conventions
| Identifier | Generated By | Purpose |
|---|
extApplicationNo | Party A | External application number, globally unique |
applicationNo | OristaPay | OristaPay application number; primary key for queries and callback payloads |
companyCode | OristaPay (generated on approval) | Company code; used for querying full profile and as company identity in subsequent transactions |
peopleId | OristaPay (generated on submission) | keyPeople global ID; used for obtaining IDV/signing links |
walletId | OristaPay (after wallet creation) | Wallet ID; used by subsequent transaction APIs |
OnboardingAPI
API Index
| # | Path | Purpose |
|---|
| 1 | POST /storage/media/dg-putObject?mediaType= | File upload (reuses the RDPAY API; not repeated in this document) |
| 2 | POST /api/v1/onboarding/application/submit | Submit onboarding application |
| 3 | POST /api/v1/onboarding/application/query | Query application progress |
| 4 | POST /api/v1/onboarding/idv/link | Get IDV link (single link completes both IDV + signing) |
| 5 | POST /api/v1/onboarding/link/refresh | Refresh link expiration |
| 6 | POST /api/v1/onboarding/profile | Query approved full company profile |
1. File Upload (FileUpload)
Interface Overview
Before submitting an onboarding application, upload company-related documents (CI / BR / articles of association / KYC / personal ID documents, etc.). Obtain fileKey and fill it into profile.
The endpoint fields are identical to the RDPAY API. See ISV Transaction API · File Upload for details.
2. Submit Application (SubmitApplication)
Interface Overview
Submit a company onboarding application for a downstream merchant (Party B). Use this endpoint for first-time submissions or resubmissions after a previous application was rejected (REJECTED).
Request Parameters
| Field Name | Type | M / O / CM | Description |
|---|
| extApplicationNo | string(128) | M | External application number generated by Party A, globally unique |
| profile | Object | M | Company profile form. See Company Profile Form for structure |
Response Parameters
| Field Name | Type | Description |
|---|
| code | int32 | Response code: 1 indicates success; other values indicate different error conditions |
| message | string | Response message |
| data | ApplicationData | Returned when application is accepted successfully |
| errors | Array<Errors> | Returned when profile validation fails (code = 6802) |
ApplicationData Field Description
| Field Name | Type | Description |
|---|
| applicationNo | string | OristaPay application number; a new number is generated on resubmission after rejection |
| applicationCreateTime | int64 | Application creation time, millisecond timestamp |
Errors Field Description
| Field Name | Type | Description |
|---|
| message | string | See Profile Error Descriptions |
Request Example
{
"extApplicationNo": "EXT20260512001",
"profile": {
"entityDetail": { "businessType": 1, "incorpPlace": "HKG" },
"businessDetail": { "list": [{ "subIndustryCode": "I300734" }] },
"shareholder": { "list": [{ "shareholderId": 1 }] },
"keyPeople": { "quorum": 2, "directorNum": 2, "people": [] },
"accountOpeningQuestionnaire": {
"accountOpeningPurposes": ["PAYMENT_FOR_HK_BUSINESS"],
"expectedMonthlyVolume": "FROM_2_5M_TO_5M_HKD",
"handleClientMoney": false
}
}
}
Response Example (Success)
{
"code": 1,
"message": "Success",
"data": {
"applicationNo": "A202605258664",
"applicationCreateTime": 1747094400000
}
}
Response Example (Profile Validation Failed)
{
"code": 6802,
"message": "Profile validation failed.",
"errors": [
{ "message": "[Business details]Industry code cannot be empty!" },
{ "message": "[Entity details]Please upload a valid proof of Business Registration" }
]
}
Key Constraints
- Idempotency key
(extApplicationNo): Repeated submissions with the same extApplicationNo and same body → returns the original applicationNo; different body → 6801
- Merchant concurrency guard: Only one active application is allowed per Party B
(CI number / BR number) under the same Party A. A new application can only be submitted after the current one reaches a final state (APPROVED / REJECTED)
- Resubmission after rejection: Must use a new
extApplicationNo; a new applicationNo is generated on submission
- Company search failure = automatic rejection: In the API path, whether it’s a company search classification failure (CI/BR not found, etc.) or a search comparison mismatch (data inconsistency), the application is directly set to
REJECTED and a REJECTED webhook is pushed. Party A must use a new extApplicationNo to resubmit
3. Query Application (QueryApplication)
Interface Overview
Query application progress by applicationNo or extApplicationNo (choose one).
Request Parameters
| Field Name | Type | M / O / CM | Description |
|---|
| applicationNo | string | CM | OristaPay application number |
| extApplicationNo | string | CM | Party A application number |
Response Parameters
| Field Name | Type | Description |
|---|
| code | int32 | Response code |
| message | string | Response message |
| data | QueryApplicationData | Returned when code = 1 |
QueryApplicationData Field Description
| Field Name | Type | Description |
|---|
| applicationNo | string | OristaPay application number |
| extApplicationNo | string | Party A application number |
| applicationCreateTime | int64 | Application creation time, millisecond timestamp |
| applicationStatus | string | Review status: UNDER_REVIEW / PENDING_USER / APPROVED / REJECTED |
| companyCode | string | Company code (returned after approval) |
| walletId | int64 | Wallet ID (returned after wallet creation) |
| profile | Object | Company profile form. See Company Profile Form |
applicationStatus values:
UNDER_REVIEW: Under acceptance or review (covers all non-final, non-pending-user stages including company search, manual review, etc.)
PENDING_USER: Company search passed; waiting for keyPeople to complete IDV/signing. Only now (and only now) can GetIdvLink be called; calling earlier returns 6406
APPROVED: Approved, wallet created. Use companyCode / walletId for subsequent business
REJECTED: Application rejected; cannot be recovered in the API scenario. Resubmit with a new extApplicationNo
The applicationStatus semantics are consistent between query and webhook. If Party A misses the PENDING_USER webhook due to a network issue, the same status can be obtained by actively calling the query API.
Each KeyPeopleInfo in profile.keyPeople.people[] includes peopleId (for obtaining IDV/signing links), and two status fields idvStatus / mandateStatus (reflecting the person’s real-time IDV/signing progress).
Request Example
{
"applicationNo": "A202605258664"
}
Response Example
{
"code": 1,
"message": "Success",
"data": {
"applicationNo": "A202605258664",
"extApplicationNo": "EXT20260512001",
"applicationCreateTime": 1747094400000,
"applicationStatus": "PENDING_USER",
"companyCode": "",
"walletId": 0,
"profile": {
"entityDetail": { "...": "..." },
"keyPeople": {
"people": [
{
"peopleId": 1000123456,
"lastNameEn": "Lo",
"firstNameEn": "Sang",
"idvStatus": "UNDER_REVIEW",
"mandateStatus": "NOT_STARTED",
"isDirector": true,
"isUbo": false
}
]
}
}
}
}
4. Get IDV Link (GetIdvLink)
Interface Overview
Generate a one-time H5 link for the specified peopleId. A single link completes both IDV → signing: Party B user opens the link, completes IDV first, and the page automatically proceeds to signing after IDV passes. For individuals with isMandateUser = false, only IDV is required; the flow ends when IDV completes.
Party A is responsible for delivering the link to Party B users (via email / SMS / QR code scan / redirect, at Party A’s discretion).
Precondition: You must first receive the ONBOARDING_APPLICATION_STATUS_NOTIFICATION webhook with applicationStatus = PENDING_USER before calling this endpoint. Before this, the backend is in the company search phase; calling will return 6406 with a message to wait for the PENDING_USER webhook.
Request Parameters
| Field Name | Type | M / O / CM | Description |
|---|
| applicationNo | string | M | OristaPay application number |
| peopleId | int64 | M | Obtained from profile.keyPeople.people[].peopleId in the QueryApplication response |
Response Parameters
| Field Name | Type | Description |
|---|
| code | int32 | Response code |
| message | string | Response message |
| data | LinkData | Returned when code = 1 |
LinkData Field Description
| Field Name | Type | Description |
|---|
| linkUrl | string | One-time H5 link; users complete IDV followed by signing after accessing |
| expireTime | int64 | Link expiration time, millisecond timestamp; default 24 hours |
Request Example
{
"applicationNo": "A202605258664",
"peopleId": 1000123456
}
Response Example
{
"code": 1,
"message": "Success",
"data": {
"linkUrl": "https://customer.oristapay.com/h5/index?code=4e0af338-9605-4353-86db-f35c4fdb7959",
"expireTime": 1747180800000
}
}
Key Constraints
- IDV Links are single-use: they expire after Party B completes the full flow (IDV + signing); unused links also expire after the timeout
- Repeated calls for the same
peopleId: unexpired link exists → returns the original link; expired → automatically invalidates the original link and generates a new one
- Returns
6001 if the person has already completed all tasks (IDV passed, and if isMandateUser=true, signing also completed)
5. Refresh Link (RefreshIdvLink)
Interface Overview
When the link has expired (expireTime < now) or is about to expire, Party A calls this endpoint to generate a new link; the original link is immediately invalidated.
Request Parameters
| Field Name | Type | M / O / CM | Description |
|---|
| applicationNo | string | M | OristaPay application number |
| peopleId | int64 | M | keyPeople global ID |
Response Parameters
LinkData: Fields are the same as §4.
Request Example
{
"applicationNo": "A202605258664",
"peopleId": 1000123456
}
Response Example
Same as §4.
Key Constraints
- Same precondition as §4: must first receive the
PENDING_USER webhook; otherwise returns 6406
- The original link is immediately invalidated after this call
- Returns
6001 if the person has already completed all tasks (IDV passed and signing completed)
- Returns
6001 if the application has been in final status (APPROVED / REJECTED)
6. Query Company Profile (QueryCompanyProfile)
Interface Overview
Query the full company profile after approval by companyCode.
Request Parameters
| Field Name | Type | M / O / CM | Description |
|---|
| companyCode | string | M | Company code (obtained from QueryApplication or Webhook after approval) |
Response Parameters
| Field Name | Type | Description |
|---|
| code | int32 | Response code |
| message | string | Response message |
| data | ProfileFormDto | Full company profile. See Company Profile Form for structure |
Request Example
{
"companyCode": "HKM12389h"
}
Response Example
{
"code": 1,
"message": "Success",
"data": {
"entityDetail": { "...": "..." },
"businessDetail": { "...": "..." },
"shareholder": { "...": "..." },
"keyPeople": { "...": "..." }
}
}
Key Constraints
- Only companies with approved status (
applicationStatus = APPROVED) can be queried; unapproved companies return 6001 + message “Profile is not approved yet.”
companyCode must belong to the current Party A; otherwise returns 6005
- The data reflects the latest OristaPay review result, which may differ from the submitted
profile (reviewers may supplement or correct certain fields)
Callback
The callback request body, signature verification, and response requirements are fully consistent with the ISV Transaction API · Callback. This document only defines the new OpenBizType values and payload fields.
1. New OpenBizType Enums
| Enum Value | Trigger |
|---|
| ONBOARDING_APPLICATION_STATUS_NOTIFICATION | Application status change (PENDING_USER / APPROVED / REJECTED) |
| ONBOARDING_KEY_PEOPLE_IDV_FAILED | A key person’s IDV failed (vendor failure or manual case failure) |
2. Callback Data Types
2.1 Application Status Change (OnboardingApplicationStatusNotification)
Trigger Timing (only key review nodes; individual node changes are not pushed)
| applicationStatus | Trigger Timing | Party A Action |
|---|
PENDING_USER | Company search passed → keyPeople IDV/signing can begin | Only now (and only now) can GetIdvLink be called (calling earlier returns 6406) |
APPROVED | Application fully approved, wallet created | Retrieve companyCode / walletId for subsequent business |
REJECTED | Application rejected in final state (includes company search failure, compliance failure, etc.) | Rejected applications cannot be recovered in the API scenario. Party A must submit a new application (do not reuse the original extApplicationNo, or the idempotency check will return the old record) |
- Newly submitted applications (first entering
UNDER_REVIEW status) do not trigger a separate webhook. Party A knows the application is accepted through the synchronous SubmitApplication response
- Node-level changes (
NameScreening → RiskScreening, etc.) are no longer pushed; only available through the QueryApplication API
- Duplicate pushes of the same
applicationStatus should be treated idempotently (deduplicated by X-Nonce)
Field Description
| Field Name | Type | Description |
|---|
| applicationNo | string | OristaPay application number |
| extApplicationNo | string | Party A application number |
| applicationStatus | string | PENDING_USER / APPROVED / REJECTED |
| companyCode | string | Company code (populated on APPROVED; empty string for other statuses) |
| walletId | int64 | Wallet ID (populated after wallet creation; 0 for other statuses) |
| eventTime | int64 | Event trigger time, millisecond timestamp |
Example (Company Search Passed, IDV Can Begin)
{
"applicationNo": "A202605258664",
"extApplicationNo": "EXT20260512001",
"applicationStatus": "PENDING_USER",
"companyCode": "",
"walletId": 0,
"eventTime": 1747094400000
}
Example (Approved)
{
"applicationNo": "A202605258664",
"extApplicationNo": "EXT20260512001",
"applicationStatus": "APPROVED",
"companyCode": "HKM12389h",
"walletId": 12345678901234,
"eventTime": 1747104400000
}
Example (Rejected / Company Search Failed)
{
"applicationNo": "A202605258664",
"extApplicationNo": "EXT20260512001",
"applicationStatus": "REJECTED",
"companyCode": "",
"walletId": 0,
"eventTime": 1747094500000
}
2.2 keyPeople IDV Failure (OnboardingKeyPeopleIdvFailedNotification)
Pushed when a key person’s IDV fails. Upon receiving this, Party A can have Party B retry IDV: call RefreshIdvLink to get a new link for Party B.
Trigger
Field Description
| Field Name | Type | Description |
|---|
| applicationNo | string | OristaPay application number |
| extApplicationNo | string | Party A application number |
| peopleId | string | keyPeople global ID (as string, preserving int64 precision) |
| eventTime | int64 | Event trigger time, millisecond timestamp |
Example
{
"applicationNo": "A202605258664",
"extApplicationNo": "EXT20260512001",
"peopleId": "1000123456",
"eventTime": 1747100100000
}
Company Profile Form
profile is the core payload for submitting an onboarding application (SubmitApplication), and also the core data returned by query APIs. The structure varies by business type (partnership / limited company / sole proprietorship) and place of incorporation.
1. Top-Level Structure
profile = {
entityDetail, // Basic entity info (required)
businessDetail, // Business info (required)
shareholder, // Shareholder info (required for limited companies only)
keyPeople, // Key people (required, includes IDV/signing subjects)
accountOpeningQuestionnaire // Account opening questionnaire (required)
}
2. Support Matrix
| Incorporation \ Business Type | Limited Company | Partnership | Sole Proprietorship |
|---|
Hong Kong (HKG) | ✓ | ✓ | ✓ |
| Other (non-HKG, and non-CHN) | ✓ | ✗ | ✗ |
3. Common Sub-structures
3.1 businessDetail.list[] Element
| Field | Type | M / O / CM | Description |
|---|
| subIndustryCode | string(10) | M | Sub-industry itemId, must exist in the OristaPay foundation industry dictionary. See Industry Code |
| yearsInBusiness | string | M | String form of the code. See Years in Business appendix |
| businessLocations | Array<string>(3) | M | Business location list, max 3. See Country/Region Code |
| lastYearSales | string | M | String form of the code. See Last Year Sales appendix |
| industryDetails | string(256) | M | Industry supplementary description |
Party A only needs to pass subIndustryCode. The primary industryCode is auto-populated by the server via dictionary lookup; any value passed by Party A will be overwritten.
3.2 KeyPeopleInfo Common Fields
All business types use KeyPeopleInfo for keyPeople.people[]. Common submission fields:
| Field | Type | M / O / CM | Description |
|---|
| lastNameEn | string(128) | CM | Either Chinese or English name required |
| firstNameEn | string(128) | CM | Either Chinese or English name required |
| nameZh | string(128) | CM | Either Chinese or English name required |
| areaCode | string(8) | O | Phone area code |
| mobileNumber | string(32) | O | Mobile number |
| email | string(128) | O | Email address |
| gender | int32 | M | 1 Male / 2 Female |
| birthdate | string | M | Date of birth, YYYY-MM-DD |
| region | string | M | Country/region of ID document. See Country/Region Code |
| idType | int32 | M | 1 Mainland China ID / 2 Hong Kong ID / 3 Passport |
| idNumber | string | M | ID document number |
| isMandateUser | boolean | M | Whether this person is a signatory. The count of isMandateUser=true in keyPeople must be ≥ keyPeople.quorum (minimum quorum). Typically some or all directors |
| ownedSharesPercent | double(6,3) | CM | Shareholding percentage (0~100, 3 decimal places). Required only when isUbo=true |
| isWalletAdmin | boolean | M | Whether this person is a wallet admin. Exactly one person in keyPeople must have isWalletAdmin=true; this person is automatically set as the company wallet super admin |
| overseaWorkCertificateFileKey | Array<string> | CM | Overseas work certificate fileKey list. Required only when isWalletAdmin=true and region=CHN (Mainland China resident); max 5 |
Two typical wallet admin configurations:
- Combined role: A director / UBO also checks
isWalletAdmin=true (one person, two roles)
- Separate role: Add a wallet-admin-only person to the
keyPeople list (set isDirector / isUbo / isPartner / isOwner all to false, only isWalletAdmin=true). This person must go through IDV
The “Mainland China ID Card” in idType is a personal document enum, distinct from “place of incorporation”. When the incorporation place is HKG but a director/shareholder is a Mainland China resident, this idType is used normally.
3.3 Runtime Fields Written Back by OristaPay
Party A must NOT populate these fields on submission; they carry write-back results from OristaPay when read via QueryApplication.
| Field | Type | Description |
|---|
| peopleId | int64 | OristaPay-generated global person ID; must be passed when obtaining IDV/signing links |
| idvStatus | string | IDV progress: NOT_STARTED / UNDER_REVIEW vendor passed + manual review / COMPLETED manual passed / FAILED |
| mandateStatus | string | Signing status (meaningful only when isMandateUser = true): NOT_STARTED / SIGNED; empty string for non-signatories |
3.4 Account Opening Questionnaire
All business types must include this module in profile.
| Field | Type | M / O / CM | Description | | | :— |:--------------| :— |:---------------------------------------------------------------------------------------------------------------------------| | accountOpeningPurposes | Array<enum> | M | Account opening purposes, select 1-2: PAYMENT_FOR_HK_BUSINESS / STORE_DIGITAL_ASSETS_FOR_HK_BUSINESS | | expectedCounterparties | string(256) | O | Expected business counterparties (free text) | | expectedMonthlyVolume | enum | M | Expected monthly volume (HKD), single choice: BELOW_1M_HKD / FROM_1M_TO_2_5M_HKD / FROM_2_5M_TO_5M_HKD / FROM_5M_TO_10M_HKD / ABOVE_10M_HKD | | handleClientMoney | string | M | Whether client money is handled (YES/NO) |
Example
"accountOpeningQuestionnaire": {
"accountOpeningPurposes": ["PAYMENT_FOR_HK_BUSINESS", "STORE_DIGITAL_ASSETS_FOR_HK_BUSINESS"],
"expectedCounterparties": "Major HK retail merchants",
"expectedMonthlyVolume": "FROM_2_5M_TO_5M_HKD",
"handleClientMoney": "NO"
}
4. Partnership Company (Hong Kong only)
entityDetail
| Field | Type | M / O / CM | Description |
|---|
| businessType | int32 | M | 2 Partnership |
| incorpPlace | string | M | Place of incorporation, only HKG supported |
| brNumber | string(32) | M | Business Registration certificate number |
| brFileKey | string(128) | M | Business Registration file fileKey |
| incorpDate | string | M | Date of incorporation, YYYY-MM-DD |
| website | string(512) | O | Website URL |
| regPlace | string | M | Registered place. See Country/Region Code |
| regAddress | string(256) | M | Registered address, English / numbers / spaces only |
| operatingPlace | string | M | Operating place |
| operatingAddress | string(256) | M | Operating address |
| nameEn | string(128) | M | Company name in English |
| nameZh | string(128) | O | Company name in Chinese |
| paFileKey | Array<string> | M | Partnership Agreement files, max 5 |
keyPeople: 2-6 partners. KeyPeopleInfo adds the following on top of common fields:
| Field | Type | M / O / CM | Description |
|---|
| isPartner | bool | M | Whether this person is a partner, always true |
Submission Example
{
"entityDetail": {
"businessType": 2,
"incorpPlace": "HKG",
"brNumber": "br-number-partner",
"incorpDate": "2025-05-01",
"website": "www.example.com",
"regPlace": "HKG",
"regAddress": "Example partner register address",
"operatingPlace": "HKG",
"operatingAddress": "Example partner operating address",
"nameEn": "Example Partnership",
"nameZh": "示例合伙公司",
"brFileKey": "4e0af338-9605-4353-86db-f35c4fdb7959.jpg",
"paFileKey": ["06993a52-3069-41c9-a048-1601a3dfade4.jpg"]
},
"businessDetail": {
"list": [
{
"subIndustryCode": "I300734",
"yearsInBusiness": "1",
"businessLocations": ["HKG"],
"lastYearSales": "1",
"industryDetails": "Digital asset platform"
}
]
},
"keyPeople": {
"quorum": 2,
"directorNum": 0,
"people": [
{
"lastNameEn": "Lo",
"firstNameEn": "Sang",
"nameZh": "罗生",
"areaCode": "852",
"mobileNumber": "61234567",
"email": "lo@example.com",
"isPartner": true,
"isMandateUser": true,
"isWalletAdmin": true
},
{
"lastNameEn": "Yeung",
"firstNameEn": "Sang",
"nameZh": "杨生",
"areaCode": "852",
"mobileNumber": "61234568",
"email": "yeung@example.com",
"isPartner": true,
"isMandateUser": true,
"isWalletAdmin": false
}
]
},
"accountOpeningQuestionnaire": {
"accountOpeningPurposes": ["PAYMENT_FOR_HK_BUSINESS"],
"expectedMonthlyVolume": "FROM_2_5M_TO_5M_HKD",
"handleClientMoney": false
}
}
5. Limited Company (Hong Kong)
entityDetail
| Field | Type | M / O / CM | Description |
|---|
| businessType | int32 | M | 1 Limited Company |
| incorpPlace | string | M | Place of incorporation, HKG |
| ciNumber | string(32) | M | Certificate of Incorporation number |
| ciFileKey | string(128) | M | Certificate of Incorporation file |
| brNumber | string(32) | M | Business Registration certificate number |
| brFileKey | string(128) | M | Business Registration file |
| incorpDate | string | M | Date of incorporation, YYYY-MM-DD |
| website | string(512) | O | Website URL |
| regPlace | string | M | Registered place of company |
| regAddress | string(256) | M | Registered address of company |
| operatingPlace | string | M | Operating place |
| operatingAddress | string(256) | M | Operating address |
| nameEn | string(128) | M | Company name in English |
| nameZh | string(128) | O | Company name in Chinese |
| isFinancialInstitute | int32 | M | 1 Regulated / 2 Non-regulated |
| financialRegulatorPlace | string | CM | Required if regulated |
| financialRegulator | string(256) | CM | Required if regulated |
| financialLicenseType | string(128) | CM | Required if regulated |
| regulatedProofKey | Array<string> | CM | Regulatory proof documents, max 5 |
| isListed | int32 | M | 1 Listed / 2 Non-listed |
| listingPlace | string(3) | CM | Required if listed |
| listingExchange | string(256) | CM | Required if listed |
| stockCode | string(128) | CM | Required if listed |
| isGovOwned | int32 | M | 1 Government-owned / 2 Non-government-owned |
| ownedGovPlace | string(3) | CM | Required if government-owned |
| maFileKey | Array<string> | M | Memorandum and Articles of Association files, max 5 |
shareholder (choose either list or shareholderFileKey)
| Field | Type | M / O / CM | Description |
|---|
| list | Array<ShareholderDto> | Either | Structured shareholder list |
| shareholderFileKey | Array<string> | Either | Shareholding structure diagram fileKey list; passing this does not require list |
Shareholder structure is required only for “Limited Company” when isFinancialInstitute=2 / isListed=2 / isGovOwned=2 (i.e., none are exempted).
ShareholderDto
| Field | Type | M / O / CM | Description |
|---|
| shareholderId | int64 | M | Unique shareholder identifier, generated by the requester |
| sameId | int64 | O | Marks “same shareholder appearing multiple times in structure”; default 0 |
| parentId | int64 | O | Parent shareholderId; use 0 for the first layer |
| shareholderType | int32 | M | 1 Individual shareholder / 2 Corporate shareholder |
| businessType | int32 | CM | Corporate shareholder business type; required when shareholderType=2 |
| incorpPlace | string | CM | Corporate shareholder place of incorporation. For partnership/sole proprietorship shareholders, only HKG supported; CHN not accepted |
| ownedSharesPercent | double(6,3) | M | Shareholding percentage of parent |
| companyNameEn | string(128) | CM | Corporate shareholder name in English (either Chinese or English name required) |
| companyNameZh | string(128) | CM | Corporate shareholder name in Chinese (either Chinese or English name required) |
| firstNameEn | string(128) | CM | Individual shareholder first name in English (either Chinese or English name required) |
| lastNameEn | string(128) | CM | Individual shareholder last name in English (either Chinese or English name required) |
| nameZh | string(128) | CM | Individual shareholder name in Chinese (either Chinese or English name required) |
keyPeople
| Field | Type | M / O / CM | Description |
|---|
| quorum | int32 | M | Minimum quorum, 1-99 |
| directorNum | int32 | M | Number of directors (must equal the count of isDirector=true), 1-99 |
| people | Array<KeyPeopleInfo> | M | List all UBOs and directors of the company |
KeyPeopleInfo adds the following on top of common fields:
| Field | Type | M / O / CM | Description |
|---|
| isDirector | boolean | M | Whether this person is a director |
| isUbo | boolean | M | Whether this person is an Ultimate Beneficial Owner (UBO) |
6. Limited Company (Non-Hong Kong)
Most fields are identical to §5. Differences are listed below (unlisted fields match §5):
| Field | Type | M / O / CM | Description |
|---|
| incorpPlace | string | M | Non-HKG country/region code; CHN not accepted |
| brNumber | string(32) | O | Business Registration certificate number (optional for non-HK regions) |
| brFileKey | string(128) | O | Business Registration file (optional for non-HK regions) |
| coiFileKey | Array<string> | CM | Certificate of Incumbency. Required when incorpPlace is BMU / WSM / SYC / CYM / VGB, max 5 |
7. Sole Proprietorship Company (Hong Kong only)
entityDetail
| Field | Type | M / O / CM | Description |
|---|
| businessType | int32 | M | 3 Sole Proprietorship |
| incorpPlace | string | M | Only HKG supported |
| brNumber | string(32) | M | Business Registration certificate number |
| brFileKey | string(128) | M | Business Registration file |
| incorpDate | string | M | Date of incorporation, YYYY-MM-DD |
| website | string(512) | O | Website URL |
| regPlace | string | M | Registered place |
| regAddress | string(256) | M | Registered address |
| operatingPlace | string | M | Operating place |
| operatingAddress | string(256) | M | Operating address |
| nameEn | string(128) | M | Company name in English |
| nameZh | string(128) | O | Company name in Chinese |
| isFinancialInstitute | int32 | O | 1 Regulated / 2 Non-regulated |
keyPeople: Exactly one owner. KeyPeopleInfo adds the following on top of common fields:
| Field | Type | M / O / CM | Description |
|---|
| isOwner | boolean | M | Whether this person is the sole proprietorship owner (exactly one) |
8. File Key Field Summary
Upload files via the file upload endpoint to obtain fileKey, then fill them into profile.
| Profile Field | File Description | Type |
|---|
| entityDetail.brFileKey | Business Registration | string |
| entityDetail.ciFileKey | Certificate of Incorporation | string |
| entityDetail.maFileKey[] | Memorandum & Articles of Association (M&A) | Array<string> ≤ 5 |
| entityDetail.paFileKey[] | Partnership Agreement | Array<string> ≤ 5 |
| entityDetail.kycFileKey[] | KYC Proof | Array<string> ≤ 5 |
| entityDetail.regulatedProofKey[] | Regulated Financial Institution Proof | Array<string> ≤ 5 |
| entityDetail.coiFileKey[] | Certificate of Incumbency | Array<string> ≤ 5 |
| keyPeople.people[].idFileKey[] | Personal ID photo | Array<string> ≤ 5 |
| keyPeople.people[].overseaWorkCertificateFileKey[] | Overseas work certificate (required for CHN wallet admin) | Array<string> ≤ 5 |
File types and limits: jpeg / jpg / png / pdf / gif, max 20 MB per file.
Error Codes
1. Business Error Codes
| code | Meaning | Typical ISV Onboarding Trigger |
|---|
1 | Success | — |
6001 | General business failure | Unclassified business error |
6002 | Parameter error | Missing required fields or type mismatch |
6003 | Order not found | applicationNo / extApplicationNo not found; peopleId not found |
6005 | No permission | Party A has not enabled ISV onboarding; or Party A queries another party’s applicationNo |
6406 | Request being processed | Company search not yet passed; wait for PENDING_USER webhook before calling GetIdvLink / RefreshIdvLink |
6801 | Duplicate application | Same extApplicationNo with different body; or same Party B (CI/BR number) already has an active application |
6802 | Profile error | profile validation failed, with errors[] list (see Profile Error Descriptions) |
6803 | Application limit reached | Party A has exceeded the account opening quota for the current period (if applicable) |
2. Per-Endpoint Error Code Reference
2.1 SubmitApplication
| Scenario | Response |
|---|
| Submission successful | code = 1 + data.applicationNo |
| Missing required fields / type error | code = 6002 |
| Party A has not enabled ISV onboarding | code = 6005 |
Same extApplicationNo, same body | code = 1 + returns original applicationNo (idempotent) |
Same extApplicationNo, different body | code = 6801 |
| Same Party B (CI/BR number) already has active application | code = 6801 |
profile validation failed | code = 6802 + errors[] |
2.2 QueryApplication
| Scenario | Response |
|---|
| Query successful | code = 1 + data |
Neither applicationNo nor extApplicationNo provided | code = 6002 |
| Application not found | code = 6003 |
| Application does not belong to current Party A | code = 6005 |
2.3 GetIdvLink
| Scenario | Response |
|---|
| Successful | code = 1 + data.linkUrl + expireTime |
applicationNo not found / not owned by current Party A | code = 6003 / 6005 |
peopleId not found / not belonging to this application | code = 6003 |
| All tasks for this person already completed | code = 6001 |
Application already in final state (APPROVED / REJECTED) | code = 6001 |
Company search not yet passed (calling before PENDING_USER webhook) | code = 6406 + message: “Company search not passed yet. Wait for PENDING_USER webhook before requesting IDV link.” |
2.4 RefreshIdvLink
| Scenario | Response |
|---|
| Successful | code = 1 |
applicationNo / peopleId not found / not owned by current Party A | code = 6003 / 6005 |
| All tasks for this person already completed | code = 6001 |
| Application already in final state | code = 6001 |
Company search not yet passed (calling before PENDING_USER webhook) | code = 6406 |
2.5 QueryCompanyProfile
| Scenario | Response |
|---|
| Successful | code = 1 + data |
companyCode not found | code = 6003 |
Company corresponding to companyCode not owned by current Party A | code = 6005 |
| Company not yet approved | code = 6001 + message “Profile is not approved yet.” |
3. Profile Error Descriptions (code = 6802)
The complete list is identical to ISV Transaction API · Profile Error Descriptions, grouped by module:
[Business details]
[Entity details]
[Key people]
[Shareholder]
[Others]
Additional rejection scenarios specific to this API set:
[Entity details]Place of incorporation not supported: CHN — incorpPlace / regPlace / operatingPlace at entity level must not be CHN
[Entity details]Place of incorporation not supported: <sanctioned country code> — Sanctioned country
[Entity details]Partnership / Sole proprietorship only support incorpPlace=HKG — Partnership / sole proprietorship is supported in Hong Kong only
[Key people]Nationality not supported: <country code> — keyPeople nationality is a sanctioned country (CHN is exempted)
[Wallet Admin]Work certification is necessary — Wallet admin with region=CHN did not provide overseaWorkCertificateFileKey