This guide walks you through building a UI module that lets Creators upload a CSV file and bulk-update records in an existing Data Model. From a single button click, the module generates an upload URL, uploads the file, runs the update, and checks job status.
Download the example module bundle to use as a starting point. After importing, replace every placeholder before using the module:
| Placeholder | Appears in | Replace with. |
|---|---|---|
REPLACE_WITH_DATA_MODEL_ID |
pluginBulkUpdateRecord |
The resource ID of the target Data Model. |
BDO Update only works with Data Model records. It does not support module submission records.
Prerequisites
- Creator or Express Administrator access to your workspace.
- A target Data Model containing the records to update.
- A CSV file with the updated values; each row must include the field used as the match key (typically
_id). - Familiarity with the Plug-In, Decisions, and File components.
Module Overview
Organize the module into three field groups: one for initialization logic, one for the Creator-facing UI, and one for the backend Plug-In component sequence.
| Name | Key | Component | Purpose |
|---|---|---|---|
| On-Load Initializer | initOnload |
Initializer | Triggers on page load. |
| Refresh Button | btnRefresh |
Button | Lets the Creator check job status manually; enabled when a job is running. |
| File Upload | fileUpload |
File | Accepts the CSV containing the updated records. |
| Enable Button Rule | ruleFileUpload |
Decisions | Enables btnBulkUpdate when a file is selected. |
| Update Button | btnBulkUpdate |
Button | Starts the upload and update sequence. |
| Success Initializer | initSuccess |
Initializer | Sets the response field to indicate success. |
| Error Initializer | initError |
Initializer | Sets the response field to indicate failure. |
| Generate Upload Link | pluginGenerateUploadLink |
Plug-In | Calls the Upload-Link endpoint to get a pre-signed URL. |
| Upload File | pluginUploadFile |
Plug-In | Posts the file bytes to the upload URL. |
| Update Records | pluginBulkUpdateRecord |
Plug-In | Calls the Update endpoint with the returned file key. |
| Get Job Status | pluginGetJobDetails |
Plug-In | Checks update progress using the job ID. |
| Check Status Rule | ruleCheckStatus |
Decisions | Shows a status message and resets the form when complete. |
The example Property IDs in this guide use a
pluginprefix (for example,pluginExport) for clarity. The platform default for Plug-In components isplug— see Property ID Naming Conventions.
How to read settings tables
The tables below describe each configurable option as it shows in the platform. Values are formatted as follows:
inline code— a value to type exactly as shown | Bold — a value selected from a drop-down, radio button, tab, or choice chip | ON/OFF — toggle state | ✓ — checkbox checked | ☐ — checkbox unchecked
Set Up the Field Groups
Create three field groups in the module to keep components organized.
| Field Group | Contains |
|---|---|
fgOnLoad |
The on-load Initializer that fires when the page renders. |
fgUI |
The buttons, file component, and enable rule the Creator interacts with. |
fgConfig |
All update Plug-In components, status logic, Initializers, and hidden fields. |
Create the Supporting Fields
Add the following fields to fgConfig. These fields carry data between components throughout the upload and update sequence.
| Property ID | Component | Default | Purpose |
|---|---|---|---|
uploadLink |
Hidden | — | Stores the pre-signed upload URL returned by pluginGenerateUploadLink. |
fileKey |
Hidden | — | Stores the Unqork file key returned after the file upload. |
jobId |
Hidden | — | Stores the update job ID returned by pluginBulkUpdateRecord. |
status |
Hidden | — | Stores the current job status returned by pluginGetJobDetails. |
response |
Hidden | — | Set to Success by initSuccess or Fail by initError. |
Configure initOnload
The initOnload Initializer component fires when the module first loads and serves as the module's entry point. It has no outputs and no connections to other components.
-
Add an Initializer component to
fgOnLoad. -
Configure the following settings:
Setting Value Property ID initOnloadTrigger Type New Submission
Configure fileUpload
The fileUpload File component captures the CSV the Creator selects. After a file is chosen, it triggers the ruleFileUpload Decisions component to enable the update button.
-
Add a File component to
fgUI. -
Configure the following settings:
Setting Value Property ID fileUploadLabel Upload FileAccepted File Types .csv -
Under Triggers, set the Post Upload drop-down to
ruleFileUpload.
Configure ruleFileUpload
The ruleFileUpload Decisions component checks whether a file has been selected and enables the btnBulkUpdate Button component when one is present. It is triggered by the fileUpload File component after each file selection.
-
Add a Decisions component to
fgUIafterfileUpload. -
Configure the following settings:
Setting Value Property ID ruleFileUploadTrigger Type Manual -
Configure the Inputs:
# Property ID Alias Type 1 fileUploadAExact -
Configure the Outputs:
# Property ID Type 1 btnBulkUpdateDisabled -
Add one row in the Decision grid:
fileUploadbtnBulkUpdate_disabled(wildcard) =IF(LEN(A)>0,'no','yes')
Configure btnBulkUpdate
The btnBulkUpdate Button component starts the upload and update sequence. It starts disabled and is enabled by the ruleFileUpload Decisions component once a file is selected. On successful validation, it triggers the pluginGenerateUploadLink Plug-In component.
-
Add a Button component to
fgUIafterruleFileUpload. -
Configure the following settings:
Setting Value Property ID btnBulkUpdateLabel Bulk UpdateAction Validate Initial State Disabled -
Under Triggers, set the On Validation Success drop-down to
pluginGenerateUploadLink.
Configure btnRefresh
The btnRefresh Button component lets the Creator manually re-check job status. It triggers the pluginGetJobDetails Plug-In component on click, and the ruleCheckStatus Decisions component enables it once a job is running. It starts disabled.
-
Add a Button component to
fgUIabovefileUpload. -
Configure the following settings:
Setting Value Property ID btnRefreshLabel RefreshAction Event Initial State Disabled -
Under Triggers, set the On Click drop-down to
pluginGetJobDetails.
Configure initSuccess
The initSuccess Initializer component sets the response field to Success when the update completes without errors.
-
Add an Initializer component to
fgConfig. -
Configure the following settings:
Setting Value Property ID initSuccessTrigger Type Manual -
Configure the Outputs:
# Property ID Type Value 1 responseValue Success
Configure initError
The initError Initializer component sets the response field to Fail when something goes wrong. All Plug-In components in fgConfig reference it as their error handler.
-
Add an Initializer component to
fgConfigafterinitSuccess. -
Configure the following settings:
Setting Value Property ID initErrorTrigger Type Manual -
Configure the Outputs:
# Property ID Type Value 1 responseValue Fail
Configure pluginGenerateUploadLink
The pluginGenerateUploadLink Plug-In component gets a pre-signed URL for uploading the file to the Unqork Cloud. It is triggered by the btnBulkUpdate Button component. On success, it triggers the pluginUploadFile Plug-In component.
-
Add a Plug-In component to
fgConfig. -
Configure the following settings:
Setting Value Property ID pluginGenerateUploadLinkTrigger Type Manual Endpoint URL https://{environment}.unqork.io/fbu/uapi/bulkOperations/uploadLinkMethod POST -
No Inputs are required for this endpoint.
-
Configure the Outputs:
# Property ID Value 1 uploadLinkuploadLink -
Under Triggers, set the Post Trigger drop-down to
pluginUploadFileand the Error Handler drop-down toinitError.
Configure pluginUploadFile
The pluginUploadFile Plug-In component posts the file bytes to the pre-signed URL using multipart/form-data. It is triggered by the pluginGenerateUploadLink Plug-In component. On success, it triggers the pluginBulkUpdateRecord Plug-In component. The endpoint URL is built dynamically from the uploadLink field.
-
Add a Plug-In component to
fgConfigafterpluginGenerateUploadLink. -
Configure the following settings:
Setting Value Property ID pluginUploadFileTrigger Type Manual Endpoint URL /api{{data.uploadLink}}Method POST Multipart ON -
Configure the Headers:
# Property ID Value 1 Connect-Typemultipart/form-data -
Configure the Inputs:
# Property ID Value 1 filefileUpload[0]['url']Enable Resolve Base64 on the
fileinput so the platform sends the file bytes rather than the base64 string. -
Configure the Outputs:
# Property ID Value 1 fileKeyfileKey -
Under Triggers, set the Post Trigger drop-down to
pluginBulkUpdateRecordand the Error Handler drop-down toinitError.
Configure pluginBulkUpdateRecord
The pluginBulkUpdateRecord Plug-In component calls the Update endpoint using the fileKey from the upload step. It is triggered by the pluginUploadFile Plug-In component. On success, it triggers the pluginGetJobDetails Plug-In component to begin polling.
-
Add a Plug-In component to
fgConfigafterpluginUploadFile. -
Configure the following settings:
Setting Value Property ID pluginBulkUpdateRecordTrigger Type Manual Endpoint URL https://{environment}.unqork.io/fbu/uapi/bulkOperations/updateMethod -
Configure the Inputs:
# Property ID Value 1 resourceId'REPLACE_WITH_DATA_MODEL_ID'2 fallbackRecordOwnercurrentUser['email']3 fileFormat'CSV'4 fileLocationfileKey5 namefileUpload[0]['name']6 storeInData'true'7 uniqueKey'_id'(or the field used to match existing records)To insert new records when no match is found, add an eighth input mapping
upsertto'true'. Whenupsertisfalse(the default), the operation skips records without a matching key. -
Configure the Outputs:
# Property ID Value 1 statusdata.status2 jobIdid -
Under Triggers, set the Post Trigger drop-down to
pluginGetJobDetailsand the Error Handler drop-down toinitError.
Configure pluginGetJobDetails
The pluginGetJobDetails Plug-In component checks the status of the update job. It is triggered by the pluginBulkUpdateRecord Plug-In component on success, and by the btnRefresh Button component when the Creator clicks it manually. On completion, it triggers the ruleCheckStatus Decisions component.
-
Add a Plug-In component to
fgConfigafterpluginBulkUpdateRecord. -
Configure the following settings:
Setting Value Property ID pluginGetJobDetailsTrigger Type Manual Endpoint URL https://{environment}.unqork.io/fbu/uapi/bulkOperations/jobs/{{data.jobId}}Method -
Configure the Outputs:
# Property ID Value 1 statusdata.status -
Under Triggers, set the Post Trigger drop-down to
ruleCheckStatus.
All BDO endpoints in this module use the
bulkOperations(camelCase, no hyphen).
Configure ruleCheckStatus
The ruleCheckStatus Decisions component reads the job status written by the pluginGetJobDetails Plug-In component, displays a pop-up message, and enables the btnRefresh Button component while the job is running. When the job reaches completed, it clears and resets fgUI so the Creator can start another update.
-
Add a Decisions component to
fgConfigafterpluginGetJobDetails. -
Configure the following settings:
Setting Value Property ID ruleCheckStatusTrigger Type Manual -
Configure the Inputs:
# Property ID Alias Type 1 jobIdAExact 2 statusExact -
Configure the Outputs:
# Property ID Type 1 btnRefreshDisabled 2 fgUIPop Message 3 fgUIMulti -
Add one row per job status in the Decision grid:
Status btnRefresh_disabledfgUI_popMessagefgUI_multicreated=IF(LEN(A)>0,'no','yes')Update started.inProgress=IF(LEN(A)>0,'no','yes')Update in progress.completed=IF(LEN(A)>0,'no','yes')Update complete.clear.resetpartiallyCompleted=IF(LEN(A)>0,'no','yes')Update partially complete.canceled=IF(LEN(A)>0,'no','yes')Update canceled.failed=IF(LEN(A)>0,'no','yes')Update failed.The formula in the disabled column uses
A(thejobIdalias). Theclear.resetmulti-action oncompletedclearsfgUIand resets the form for the next update.
Prepare the CSV
The bulk update CSV differs from a bulk upload CSV. Each row must include the value used as the match key so the platform can locate the record to update. By default, this is the _id column.
The CSV requires the following columns:
| Column | Required | Description |
|---|---|---|
_id |
Yes (or your chosen uniqueKey) |
The Unqork submission ID of the record to update (24-character hexadecimal string). |
| Any Data Model field | Yes (at least one) | Column headers must match the Data Model field keys exactly; only the columns present in the file are updated. |
A complete CSV looks like this:
_id,firstName,lastName,email
6abeb2b1277a9f5cd3918aca,Todd,Smith,todd.smith@example.com
6abeb2b1277a9f5cd3918acb,Aisha,Patel,aisha.patel@example.com
6abeb2b1277a9f5cd3918acc,Liam,Nguyen,liam.nguyen@example.com
To find the
_idvalues for records you want to update, you can either:
- Export the records using the Build a Bulk Download Module guide, then edit the downloaded file and re-upload it here.
- Open the Explorer tab in the platform, navigate to Utilities > Record Collections > Modules > your module name, and copy the
_idfrom the record you want to update.
Test the Module
- Open the module in Preview.
- Select a CSV file formatted as described in Prepare the CSV. The Bulk Update button enables when a file is present.
- Click Bulk Update.
- Click Refresh until the pop-up message reads
Update complete. - Open the submission using the platform's submission inspection method. See Debugger for how to access submission data from Express View.
- Confirm the
jobIdandstatusfields contain the expected values. - Navigate to the target Data Model's Record Collection to verify the updated records reflect the values from the CSV.
Changelog
| Date | Change. |
|---|---|
| 2026-10-05 | Added Prepare the CSV section explaining column structure and the _id match key requirement. |
| 2026-10-05 | Updated bundle from tested POC; corrected pluginBulkUpdateRecord input from dataModelOrModuleId to resourceId. |
| 2026-10-05 | Full restructure: field groups table, per-component Configure sections, Inputs/Outputs as UI-matching tables, Test the Module section, bundle download link. |
| 2026-09-30 | Initial publication. |