Captures and verifies two identities simultaneously as a paired unit, triggering one combined API fetch. Use for paired records like marriage lookups or joint applicants.
Read Form Rules before using this component — keys, labels, required fields, expressions, visibility, and validation all follow shared conventions.
- Two identities must be verified together against a single integration endpoint (e.g. a marriage record lookup)
- The response is a combined payload that populates fields for both identities
- A single document type dropdown can serve both sub-fields
Instead of customdoubleidinput, use… |
For… |
Two customidinput fields |
Independent fetches with separate result sets per identity |
customidinput |
A single identity lookup |
customcrvsidinput |
A CRVS (Civil Registration) lookup keyed by a single identity |
| Prop |
Type |
Required? |
Description |
label |
string |
required |
Field label. Can be empty if sub-labels carry the context. |
url |
string |
required |
Integration endpoint path — always /integration/v1/fetch/sync. |
endpointCode |
string |
required |
Integration endpoint code that identifies the lookup service. |
allowedDocumentTypes |
array |
required |
List of accepted document type objects — see shape below. |
required |
boolean |
required |
Always false. The expression controls the runtime value. |
defaultRequired |
boolean |
required |
true for required fields, false for optional ones. |
useBaseUrl |
boolean |
optional |
Prepend the API gateway base URL to url. Set true for production endpoints. |
populates |
array |
optional |
{ valueKey, targetKey } mappings that auto-fill downstream fields from the response. |
firstIdentityLabel |
string |
optional |
Label above the first identity sub-field. Default "First Identity". |
firstIdentityPlaceholder |
string |
optional |
Placeholder for the first identity input. |
firstIdentityValueKey |
string |
optional |
Response + payload key for the first document number. Default "firstDocumentNumber". |
firstIdentityDocumentTypeKey |
string |
optional |
Payload key for the first document type. Default "firstDocumentType". |
secondIdentityLabel |
string |
optional |
Label above the second identity sub-field. Default "Second Identity". |
secondIdentityPlaceholder |
string |
optional |
Placeholder for the second identity input. |
secondIdentityValueKey |
string |
optional |
Response + payload key for the second document number. Default "secondDocumentNumber". |
secondIdentityDocumentTypeKey |
string |
optional |
Payload key for the second document type. Default "secondDocumentType". |
hideField |
boolean |
optional |
Hides the field and excludes its value from submission. Toggle via expressions["props.hideField"]. |
| Key |
Type |
Description |
label |
string |
Display name shown in the document type dropdown. |
value |
string |
Code sent in the API payload (e.g. "NID", "PASSPORT_ID"). |
pattern |
string |
Regex the entered document number must match. |
maxLength |
number |
Maximum character count for the document number. |
minLength |
number |
Minimum character count for the document number. |
placeholder |
string |
Optional custom placeholder for this document type. |
{
"key": "COUPLE_IDENTITY",
"type": "customdoubleidinput",
"props": {
"label": "",
"required": false,
"defaultRequired": true,
"url": "/integration/v1/fetch/sync",
"useBaseUrl": true,
"endpointCode": "FGETMARRIAGERECORD",
"firstIdentityLabel": "Husband",
"secondIdentityLabel": "Wife",
"allowedDocumentTypes": [
{
"label": "National ID",
"value": "NID",
"pattern": "^\\d*$",
"maxLength": 16,
"minLength": 16
}
]
},
"expressions": {
"props.required": "!(field?.props?.hideField || field?.hide) && field?.props?.defaultRequired"
},
"validation": {
"messages": {
"required": "This field is required.",
"invalidInput": "Invalid identity document."
}
}
}
{
"key": "COUPLE_IDENTITY",
"type": "customdoubleidinput",
"props": {
"label": "",
"required": false,
"defaultRequired": true,
"url": "/integration/v1/fetch/sync",
"useBaseUrl": true,
"endpointCode": "FGETMARRIAGERECORD",
"firstIdentityLabel": "Husband",
"firstIdentityPlaceholder": "Husband's Details",
"firstIdentityValueKey": "HUSBAND_DOCUMENT_NUMBER",
"firstIdentityDocumentTypeKey": "HUSBAND_DOCUMENT_TYPE",
"secondIdentityLabel": "Wife",
"secondIdentityPlaceholder": "Wife's Details",
"secondIdentityValueKey": "WIFE_DOCUMENT_NUMBER",
"secondIdentityDocumentTypeKey": "WIFE_DOCUMENT_TYPE",
"allowedDocumentTypes": [
{
"label": "National ID",
"value": "NID",
"pattern": "^\\d*$",
"maxLength": 16,
"minLength": 16
},
{
"label": "Passport",
"value": "PASSPORT_ID",
"pattern": "^[a-zA-Z0-9]*$",
"maxLength": 10,
"minLength": 5
}
],
"populates": [
{ "valueKey": "husbandDetails.surName", "targetKey": "HUSBAND_SURNAME" },
{ "valueKey": "civilStatusOfficeName", "targetKey": "OFFICE_OF_REGISTRATION" }
]
},
"expressions": {
"props.required": "!(field?.props?.hideField || field?.hide) && field?.props?.defaultRequired"
},
"validation": {
"messages": {
"required": "This field is required.",
"invalidInput": "Invalid identity document."
}
}
}
- Setting
required: true directly — use the required: false + defaultRequired: true + expression pattern from Form Rules.
- Omitting
url — the component throws at runtime; always set it to /integration/v1/fetch/sync.
- Omitting
endpointCode — the component throws at runtime; always required.
- Omitting
allowedDocumentTypes — the document type dropdown renders empty and the user cannot select a type.
- Using
customdoubleidinput when the two identities trigger independent fetches with separate result sets — use two customidinput fields instead.
- Using dot-notation
valueKey (e.g. "husbandDetails.surName") without confirming the API response uses nested objects — flat keys are safer unless the response shape is verified.