The fetch fields a service manager can add
| Field (palette) | Type | How the endpoint is set | Good for |
|---|---|---|---|
| Generic data fetch | customgenericdatafetch |
Free-text Endpoint Code in the field settings | Any lookup: serial, reference number, TIN |
| National ID | customidinput |
Palette default NIDAGETIDINFO; no endpoint setting |
NID lookup that fills names |
| Dropdown with data fetch | customdropdown (CUSTOM_DROPDOWN_DATAFETCH) |
Integration picker listing FFORWARD endpoints | Option lists that do not depend on the form |
| OTP data fetch | Endpoint Code | Lookups confirmed with a one-time code | |
| Advanced palette | conditional fetch, fetch button, paginated dropdown, multi-select | Endpoint Code; paginated lists call /integration/v1/fetch/paginated |
Fetches that depend on other fields, long lists |
The router lookup of Assignment 3, step by step, in the Form step of your change request.
Drag Generic data fetch into the section. Give it the key routerNumber: the CanalBox push reads that key later.
Type COURSE_CANALBOX_VERIFY_USER, exactly. Codes are case-sensitive.
Choose when the call fires: TRIGGER_BUTTON (the applicant clicks), INPUT_LENGTH (after N characters), FIELD_LISTENER (when other fields have values).
Either one payloadKey (the field value is sent under that name) or payloadKeyMappings built from other fields and constants.
Map a response path (valueKey, dotted when the answer is nested) to a form field (targetKey). The course endpoints return flat fields, so accountName is enough.
Use the form preview on staging with the test router CBXK0001. Watch the network call and the filled fields, then try CBXK9999 to see the error.
They type the serial, click the fetch button, and the owner's name and current package appear, usually read-only.
Generic data fetch field: the CanalBox router lookup on staging
{
"key": "routerNumber",
"type": "customgenericdatafetch",
"props": {
"label": "Router serial number",
"url": "/integration/v1/fetch/sync",
"useBaseUrl": true,
"endpointCode": "COURSE_CANALBOX_VERIFY_USER",
"triggerType": "TRIGGER_BUTTON",
"payloadKey": "routerNumber",
"populates": [
{ "valueKey": "accountName", "targetKey": "accountName" },
{ "valueKey": "currentPackage", "targetKey": "currentPackage" }
]
}
}
{"routerNumber": value}accountName goes into the form field accountNameWhat the browser sends
POST /integration/v1/fetch/sync
{
"endpointCode": "COURSE_CANALBOX_VERIFY_USER",
"callerId": "<generated per call>",
"requester": "<random id per call>",
"payload": { "routerNumber": "CBXK0001" }
}
What comes back
200 data.response (a JSON string, parsed by the form):
{
"routerNumber": "CBXK0001",
"accountName": "Claudine Uwase",
"currentPackage": "CanalBox 50 Mbps",
"subscriptionStatus": "ACTIVE",
"endDate": "2026-10-20",
"currency": "RWF"
}
400 when the router is unknown (try CBXK9999):
{
"responseCode": "CANALBOX_ROUTER_NOT_ELIGIBLE",
"responseMessage": "No CanalBox subscription matches this router or phone number."
}
400 same code, another message, for the router being moved (CBXK0003):
"responseMessage": "This router is being moved to a new address. Renew after the move is complete."
A list from a fetch
{
"key": "phoneRouter",
"type": "customdropdowndatafetchpaginated",
"props": {
"label": "Router",
"required": false,
"defaultRequired": true,
"url": "/integration/v1/fetch/sync",
"useBaseUrl": true,
"endpointCode": "COURSE_CANALBOX_ROUTERS_BY_PHONE",
"triggerType": "FIELD_LISTENER",
"payloadKey": "phoneNumber",
"bindLabel": "label",
"bindValue": "routerNumber",
"dataset": { "dataField": "routers", "pagination": true, "searching": false },
"populates": [
{ "valueKey": "accountName", "targetKey": "accountName" },
{ "valueKey": "currentPackage", "targetKey": "currentPackage" }
]
}
}
dataField is the array inside the answer; bindLabel and bindValue are keys of each itemtriggerType: FIELD_LISTENER is required, or the dropdown never loadspayloadKeyMappings
"payloadKeyMappings": [
{ "key": "phone", "sourceField": "phoneNumber" },
{ "key": "country", "isStatic": true, "staticValue": "RW" },
{ "key": "nid", "sourceField": "applicantNid", "searchInRootForm": true }
]
searchInRootForm reads a field in another sectionRead it in an expression
formState?.FETCHED_DATA?.routerNumber?.endDate
formState.FETCHED_DATA[fieldKey]Trigger types
| Trigger | Fires | Use it for |
|---|---|---|
TRIGGER_BUTTON |
When the applicant clicks the fetch button | Most lookups: clear and predictable |
INPUT_LENGTH |
When the value reaches the configured length | Fixed-length identifiers (NID, 8-character router serial) |
FIELD_LISTENER |
Once every source field has a value (debounced) | Lookups built from several fields |
ON_SUCCESS |
After another fetch succeeds (advanced palette only) | Chained lookups |
Gotcha · four classic fetch mistakes
- Populating a field in another section. By default targetKey only reaches sibling fields. Tick Enable populating of fields in all form sections, or keep the target next to the fetch field.
- Populating from an array. Responses are flattened into indexed keys (
offers.0.name), so a valueKey pointing at a whole array fills nothing useful. Show a list with a dropdown that fetches (above), or read it fromformState.FETCHED_DATA.- NID field without a code. It shows CONFIGURATION ERROR! and becomes read-only. Keep the palette default unless told otherwise.
- Confusing "usePrefetch" with a fetch. On NID and TIN fields it means "prefetch the value from the user profile". It calls no endpoint.
Gotcha · the Integration picker sends no form values
The Dropdown with data fetch Integration picker only sends the endpoint code. It cannot filter by what the applicant typed. For a list that depends on the form (the routers of a phone number), use the paginated dropdown with data fetch (
customdropdowndatafetchpaginated) and apayloadKey, as in the example above.
Tip · component reference
Every fetch component has a reference page with all its properties: Conditional generic fetch, Dropdown with data fetch, Paginated dropdown with data fetch, NID widget, and Form state for
FETCHED_DATA.
Tip · test against a mock first
When the partner is not ready, ask the integration manager for a mock of the endpoint. The CanalBox endpoints of this course already call mocks, so the test data in lesson C4 always answers the same way. How mocks are built is part of Course 2 (IM guide).
Your fetch fills accountName on staging, but a field in the next section stays empty. Most likely?
C. The call worked (accountName is filled). Cross-section targets need the setting.
← C1 · Integrations for service managers · C3 · Push from the workflow →