Preliminary KYC Information
The Preliminary KYC Information API returns the general information captured at customer creation time — the static identity block recorded when the customer profile was created, plus the answers given to the tenant's preliminary (dynamic) KYC fields.
GET {base_url}/ExtCustomerManagement/GetPreliminaryAnswers/{submissionId}
Every answer is returned already labelled with the field it was captured against — its name, its display label, and its type. No separate call to fetch the form definition is required.
Authentication
All requests require a bearer token in the Authorization header:
Authorization: Bearer your-token-here
The endpoint is tenant-scoped by the token. For details on obtaining a token, see Authentication.
Integration Steps
- Call the endpoint with the customer's
submissionId. This is the same submission identifier used by Customer Details. - Check for an empty result.
resultisnullwhen the submission has no linked individual or legal entity record. - Render the identity block. Use
result.identity, switching onisLegalEntityto decide whether to show individual fields (first/middle/last name) or legal entity fields (registration number, trading name). - Render the answers. Iterate
result.dynamicAnswers.answers. Each entry carriesfieldLabelfor display andfieldTypeIdto decide how to format the value, so answers can be rendered directly without resolving anything against a form definition. - Read each value from its payload. The captured value lives on
answer, under the property matching the field type —textValue,date,countryId, and so on. - Tolerate missing labels.
fieldName,fieldLabelandfieldTypeIdarenullwhen the field has since been deleted from the form. The answer is still returned with itsfieldId.
Request
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
submissionId | string | Yes | The unique identifier of the customer submission |
Example Request
GET {base_url}/ExtCustomerManagement/GetPreliminaryAnswers/a1b2c3d4-5e6f-4a7b-9c8d-1e2f3a4b5c6d
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Response
{
"version": null,
"statusCode": 200,
"messages": [
"Processed successfully"
],
"result": {
"identity": {
"isLegalEntity": false,
"firstName": "John",
"middleName": null,
"lastName": "Smith",
"fullName": "John Smith",
"email": "john.smith@example.com",
"phoneNumber": "+971500000000",
"registrationNumber": null,
"tradingName": null,
"customerCode": "CUST-00123"
},
"assignedOfficerName": "Sara Ahmed",
"primaryClientName": "Acme Bank",
"dynamicAnswers": {
"id": "sub-dyn-7f31",
"userDetailsId": "user-12345",
"companyId": null,
"formId": "6f2c1b90-4a77-4f6e-9c31-2a5d7e1b8c44",
"answers": [
{
"fieldId": "3c2403cd-7067-4c08-821b-9fb2e5751c4f",
"fieldName": "PointOfContact",
"fieldLabel": "Point of contact",
"fieldTypeId": "Text",
"answer": {
"id": "ans-12345",
"fieldID": "3c2403cd-7067-4c08-821b-9fb2e5751c4f",
"fieldTypeId": "Text",
"textValue": "Branch walk-in"
}
},
{
"fieldId": "5d10fd74-658b-41d5-8fed-2d60d52a89c0",
"fieldName": "RelationshipStartDate",
"fieldLabel": "Relationship start date",
"fieldTypeId": "DatePicker",
"answer": {
"id": "ans-67890",
"fieldID": "5d10fd74-658b-41d5-8fed-2d60d52a89c0",
"fieldTypeId": "DatePicker",
"date": "2025-11-04"
}
},
{
"fieldId": "308fec76-b67f-45ec-81e2-06cff19b7c35",
"fieldName": "SourceOfIntroduction",
"fieldLabel": "Source of introduction",
"fieldTypeId": "SingleOptionSelect",
"answer": {
"id": "ans-11111",
"fieldID": "308fec76-b67f-45ec-81e2-06cff19b7c35",
"fieldTypeId": "SingleOptionSelect",
"optionId": "opt-4c21",
"option": {
"id": "opt-4c21",
"optionText": "Branch referral",
"optionValue": "branch_referral",
"order": 2
},
"singleOptionSelectAnswerItems": null
}
}
]
}
}
}
Response Fields
| Field | Type | Description |
|---|---|---|
identity | object | Identity data captured when the customer was created |
assignedOfficerName | string | Full name of the officer assigned to the submission. Returns Unassigned when no active assignment exists |
primaryClientName | string | Name of the submission's primary active client (nullable) |
dynamicAnswers | object | The customer's preliminary dynamic-field answers (nullable) |
Identity Fields
| Field | Type | Description |
|---|---|---|
isLegalEntity | boolean | false for individual customers, true for legal entities. Determines which of the fields below are populated |
firstName | string | First name (individual only) |
middleName | string | Middle name (individual only) |
lastName | string | Last name (individual only) |
fullName | string | Full name of the individual, or the registered name of the legal entity |
email | string | Email address captured at creation |
phoneNumber | string | Mobile number for individuals, phone number for legal entities |
registrationNumber | string | Commercial registration number (legal entity only) |
tradingName | string | Trading name (legal entity only) |
customerCode | string | Tenant-assigned customer code |
Fields that do not apply to the entity type are returned as null.
Dynamic Answers Fields
| Field | Type | Description |
|---|---|---|
id | string | Identifier of the preliminary dynamic-fields submission. This is not the main KYC submission id you passed in |
userDetailsId | string | Identifier of the individual customer (nullable) |
companyId | string | Identifier of the legal entity customer (nullable) |
formId | string | Identifier of the dynamic-fields form the answers belong to |
answers | array | Answers captured against the form's fields |
Answer Fields
Each entry in answers pairs one captured answer with the identity of its field:
| Field | Type | Description |
|---|---|---|
fieldId | string | Unique identifier of the field the answer was captured against |
fieldName | string | Machine name of the field (e.g. PointOfContact). null if the field has been deleted |
fieldLabel | string | Human-readable caption of the field (e.g. Point of contact). null if the field has been deleted |
fieldTypeId | string | Field type name (e.g. Text, TextArea, DatePicker). null if the field has been deleted |
answer | object | The answer payload itself |
The answer object is the standard polymorphic answer shape used across the platform: id, fieldID, fieldTypeId, and one or more type-specific value properties (textValue, date, countryId, and so on). It is passed through untouched, so no answer type loses detail. See Get Submission and the Answer Models section for the per-type shapes.
Option-based types (SingleOptionSelect, SingleOptionRadio) return the selected optionId alongside an expanded option object containing optionText, optionValue and order. SingleOptionSelect also carries singleOptionSelectAnswerItems, which is populated only for fields configured to accept multiple selections and is null otherwise.
Use fieldName, fieldLabel and fieldTypeId from the answer entry rather than anything nested inside answer. They are resolved from the current form definition specifically so that external consumers do not need to fetch the form.
Both of these are 200 responses that your integration must handle:
resultisnull— the submission is not linked to an individual or a legal entity record.result.dynamicAnswersisnull— the tenant has no preliminary form configured, or the customer has no captured answers. Theidentityblock is still returned and should still be rendered.
Example: Rendering the Preliminary Information
const response = await fetch(
`${baseUrl}/ExtCustomerManagement/GetPreliminaryAnswers/${submissionId}`,
{ headers: { Authorization: `Bearer ${token}` } }
).then((r) => r.json());
const profile = response.result;
if (!profile) {
// Submission has no linked customer record
return null;
}
const { identity } = profile;
const displayName = identity.isLegalEntity
? identity.tradingName ?? identity.fullName
: [identity.firstName, identity.middleName, identity.lastName].filter(Boolean).join(' ');
const rows = (profile.dynamicAnswers?.answers ?? []).map((entry) => ({
// Fall back to the field id when the field has since been deleted
label: entry.fieldLabel ?? entry.fieldName ?? entry.fieldId,
fieldType: entry.fieldTypeId,
value: readValue(entry),
}));
function readValue(entry) {
switch (entry.fieldTypeId) {
case 'Text':
case 'TextArea':
return entry.answer.textValue;
case 'DatePicker':
return entry.answer.date;
case 'SingleOptionSelect':
case 'SingleOptionRadio':
// `option` carries the display text; `optionId` alone is enough to store the choice
return entry.answer.option?.optionText ?? entry.answer.optionId;
case 'Country':
return entry.answer.countryId;
default:
return entry.answer; // Hand off to a type-specific renderer
}
}
Error Handling
| Status Code | Description | Solution |
|---|---|---|
| 400 | Submission not found | Verify the submissionId exists and belongs to your tenant |
| 401 | Unauthorized access | Check the authentication token and tenant permissions |
| 429 | Too many requests | Implement rate limiting |
Best Practices
- Drive your rendering off
fieldTypeId. It tells you which property onanswerholds the value and how it should be formatted. - Always fall back when labels are null. A field deleted from the form after an answer was captured leaves
fieldName,fieldLabelandfieldTypeIdempty. The answer is still returned, so fall back tofieldIdrather than dropping the row. - Do not assume every field has an answer. Fields with no captured value are simply absent from the
answersarray — the array reflects what was answered, not the full form. - Do not treat
dynamicAnswers.idas the customer's submission id. It identifies the preliminary dynamic-fields submission, which is a separate record from the main KYC submission.
Related Resources
- Customer Details — onboarding status and progress for a submission
- Customer Profile Management — creating and retrieving customer profiles
- Get Submission — answer payload shapes by field type
- Get Form Fields — field type catalogue