Skip to main content

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

  1. Call the endpoint with the customer's submissionId. This is the same submission identifier used by Customer Details.
  2. Check for an empty result. result is null when the submission has no linked individual or legal entity record.
  3. Render the identity block. Use result.identity, switching on isLegalEntity to decide whether to show individual fields (first/middle/last name) or legal entity fields (registration number, trading name).
  4. Render the answers. Iterate result.dynamicAnswers.answers. Each entry carries fieldLabel for display and fieldTypeId to decide how to format the value, so answers can be rendered directly without resolving anything against a form definition.
  5. 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.
  6. Tolerate missing labels. fieldName, fieldLabel and fieldTypeId are null when the field has since been deleted from the form. The answer is still returned with its fieldId.

Request

Path Parameters

ParameterTypeRequiredDescription
submissionIdstringYesThe 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

FieldTypeDescription
identityobjectIdentity data captured when the customer was created
assignedOfficerNamestringFull name of the officer assigned to the submission. Returns Unassigned when no active assignment exists
primaryClientNamestringName of the submission's primary active client (nullable)
dynamicAnswersobjectThe customer's preliminary dynamic-field answers (nullable)

Identity Fields

FieldTypeDescription
isLegalEntitybooleanfalse for individual customers, true for legal entities. Determines which of the fields below are populated
firstNamestringFirst name (individual only)
middleNamestringMiddle name (individual only)
lastNamestringLast name (individual only)
fullNamestringFull name of the individual, or the registered name of the legal entity
emailstringEmail address captured at creation
phoneNumberstringMobile number for individuals, phone number for legal entities
registrationNumberstringCommercial registration number (legal entity only)
tradingNamestringTrading name (legal entity only)
customerCodestringTenant-assigned customer code

Fields that do not apply to the entity type are returned as null.

Dynamic Answers Fields

FieldTypeDescription
idstringIdentifier of the preliminary dynamic-fields submission. This is not the main KYC submission id you passed in
userDetailsIdstringIdentifier of the individual customer (nullable)
companyIdstringIdentifier of the legal entity customer (nullable)
formIdstringIdentifier of the dynamic-fields form the answers belong to
answersarrayAnswers captured against the form's fields

Answer Fields

Each entry in answers pairs one captured answer with the identity of its field:

FieldTypeDescription
fieldIdstringUnique identifier of the field the answer was captured against
fieldNamestringMachine name of the field (e.g. PointOfContact). null if the field has been deleted
fieldLabelstringHuman-readable caption of the field (e.g. Point of contact). null if the field has been deleted
fieldTypeIdstringField type name (e.g. Text, TextArea, DatePicker). null if the field has been deleted
answerobjectThe 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.

Prefer the labels on the wrapper

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.

Empty results are not errors

Both of these are 200 responses that your integration must handle:

  • result is null — the submission is not linked to an individual or a legal entity record.
  • result.dynamicAnswers is null — the tenant has no preliminary form configured, or the customer has no captured answers. The identity block 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 CodeDescriptionSolution
400Submission not foundVerify the submissionId exists and belongs to your tenant
401Unauthorized accessCheck the authentication token and tenant permissions
429Too many requestsImplement rate limiting

Best Practices

  • Drive your rendering off fieldTypeId. It tells you which property on answer holds 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, fieldLabel and fieldTypeId empty. The answer is still returned, so fall back to fieldId rather than dropping the row.
  • Do not assume every field has an answer. Fields with no captured value are simply absent from the answers array — the array reflects what was answered, not the full form.
  • Do not treat dynamicAnswers.id as the customer's submission id. It identifies the preliminary dynamic-fields submission, which is a separate record from the main KYC submission.