This guide walks you through building a UI module that deletes submission records in bulk. The module handles the two-stage delete process: archiving records first (soft delete), then permanently removing them if needed (hard delete). Creators set the date range in the UI, and the module displays job status after each stage.
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 |
pluginDelete, pluginHardDelete |
The resource ID of the Data Model or module containing the records to delete. |
BDO Delete is disabled by default. Contact an Unqork representative to enable it for your environment. Hard delete is permanent and cannot be reversed.
Prerequisites
- Creator or Express Administrator access to your workspace.
- The BDO Delete endpoint enabled by an Unqork representative.
- The resource ID of the Data Model or module containing the records to delete.
- Familiarity with the Plug-In, Decisions, and Button 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. |
| Delete Button | btnDelete |
Button | Starts the soft-delete sequence. |
| Hard Delete Button | btnHardDelete |
Button | Starts the hard-delete sequence; enabled when soft delete completes. |
| Start Date | startDate |
Date | Filters records created after this date. |
| End Date | endDate |
Date Input | Filters records created on or before this date. |
| Error Initializer | initError |
Initializer | Sets the response field to indicate failure. |
| Soft Delete | pluginDelete |
Plug-In | Calls the Delete endpoint to archive records in the date range. |
| Hard Delete | pluginHardDelete |
Plug-In | Calls the Delete endpoint with destroy=true to permanently remove archived records. |
| Get Job Status | pluginGetJobDetails |
Plug-In | Checks delete progress using the job ID. |
| Check Status Rule | ruleCheckStatus |
Decisions | Shows a status message and enables the btnHardDelete Button component when soft delete is 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, date inputs, and HTML instructions the Creator interacts with. |
fgConfig |
All Plug-In components, status logic, the error Initializer, and hidden fields. |
Create the Supporting Fields
Add the following fields to fgConfig. These fields carry data between components throughout the delete sequence.
| Property ID | Component | Default | Purpose |
|---|---|---|---|
jobId |
Hidden | — | Stores the delete job ID returned by pluginDelete or pluginHardDelete. |
status |
Hidden | — | Stores the current job status returned by pluginGetJobDetails. |
response |
Hidden | — | Set to Fail by initError when any Plug-In encounters an error. |
Before You Begin
Unqork recommends exporting a copy of records before running a bulk delete. See Build a Bulk Download Module for those steps.
BDO Delete removes a maximum of 500,000 records per operation. For larger collections, run the operation multiple times.
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 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
fgUI. -
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 btnDelete
The btnDelete Button component starts the soft-delete sequence. After validation passes, it triggers the pluginDelete Plug-In component.
-
Add a Button component to
fgUIafter the Refresh button. -
Configure the following settings:
Setting Value Property ID btnDeleteLabel Delete RecordsAction Validate Theme Danger -
Under Triggers, set the On Validation Success drop-down to
pluginDelete.
Configure btnHardDelete
The btnHardDelete Button component permanently removes the archived records. It starts disabled and is enabled by the ruleCheckStatus Decisions component only after the soft delete reaches completed. After validation passes, it triggers the pluginHardDelete Plug-In component.
-
Add a Button component to
fgUIafterbtnDelete. -
Configure the following settings:
Setting Value Property ID btnHardDeleteLabel Permanently DeleteAction Validate Theme Danger Initial State Disabled -
Under Triggers, set the On Validation Success drop-down to
pluginHardDelete.
Configure startDate
The startDate Date Input lets the Creator specify the start of the date range. The pluginDelete Plug-In component and the pluginHardDelete Plug-In component read its value as dateFieldStartToFilterOn.
-
Add a Date Input component to
fgUIafter the buttons. -
Configure the following settings:
Setting Value Property ID startDateLabel Start Date (created after)Required ON
Configure endDate
The endDate Date Input lets the Creator specify the end of the date range. The pluginDelete Plug-In component and the pluginHardDelete Plug-In component read its value as dateFieldEndToFilterOn.
-
Add a Date Input component to
fgUIafterstartDate. -
Configure the following settings:
Setting Value Property ID endDateLabel End Date (created on/before)Required ON
Configure initError
The initError Initializer component sets the response field to Fail when something goes wrong. Both delete Plug-Ins reference it as their error handler.
-
Add an Initializer component to
fgConfig. -
Configure the following settings:
Setting Value Property ID initErrorTrigger Type Manual -
Configure the Outputs:
# Property ID Type Value 1 responseValue Fail
Configure pluginDelete
The pluginDelete Plug-In component calls the Delete endpoint to archive records in the selected date range (soft delete). It is triggered by the btnDelete Button component. On success, it triggers the pluginGetJobDetails Plug-In component to begin polling.
-
Add a Plug-In component to
fgConfig. -
Configure the following settings:
Setting Value Property ID pluginDeleteTrigger Type Manual Endpoint URL https://{environment}.unqork.io/fbu/uapi/bulkOperations/deleteMethod POST -
Configure the Inputs:
# Property ID Value 1 resourceId'REPLACE_WITH_DATA_MODEL_ID'2 name'Bulk Delete'3 dateFieldToFilterOn'created'4 dateFieldStartToFilterOnstartDate5 dateFieldEndToFilterOnendDate -
Configure the Outputs:
# Property ID Value 1 jobIdid -
Under Triggers, set the Post Trigger drop-down to
pluginGetJobDetailsand the Error Handler drop-down toinitError.
To delete records from a previous Export operation instead, set
dataSourceto'EXPORT'and includeexportOperationIdas an additional input. See Bulk Data Operations for all available parameters.
Configure pluginHardDelete
The pluginHardDelete Plug-In component permanently removes all archived records in the same date range. It is triggered by the btnHardDelete Button component after the soft delete completes, and targets only ARCHIVED records to avoid affecting active records.
-
Add a Plug-In component to
fgConfigafterpluginDelete. -
Configure the following settings:
Setting Value Property ID pluginHardDeleteTrigger Type Manual Endpoint URL https://{environment}.unqork.io/fbu/uapi/bulkOperations/delete?destroy=trueMethod POST -
Configure the Inputs:
# Property ID Value 1 resourceId'REPLACE_WITH_DATA_MODEL_ID'2 name'Bulk Hard Delete'3 targetRecordType'ARCHIVED'4 dateFieldToFilterOn'created'5 dateFieldStartToFilterOnstartDate6 dateFieldEndToFilterOnendDate -
Configure the Outputs:
# Property ID Value 1 jobIdid -
Under Triggers, set the Post Trigger drop-down to
pluginGetJobDetailsand the Error Handler drop-down toinitError.
Hard delete is permanent. Unqork cannot recover records after this step completes.
Configure pluginGetJobDetails
The pluginGetJobDetails Plug-In component checks the status of the current delete job. It is triggered by both the pluginDelete Plug-In component and the pluginHardDelete 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
fgConfigafterpluginHardDelete. -
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 from the pluginGetJobDetails Plug-In component, triggers a pop-up message, and enables the btnRefresh Button component while a job is running. When the soft delete reaches completed, it also enables the btnHardDelete Button component so the Creator can proceed to the permanent delete.
-
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 btnHardDeleteDisabled 3 fgUIPop Message -
Add one row per job status in the Decision grid:
Status btnRefresh_disabledbtnHardDelete_disabledfgUI_popMessagecreated=IF(LEN(A)>0,'no','yes')yesDelete started.inProgress=IF(LEN(A)>0,'no','yes')yesDelete in progress.completed=IF(LEN(A)>0,'no','yes')noRecords archived. Click Permanently Delete to remove them, or leave them archived.partiallyCompleted=IF(LEN(A)>0,'no','yes')yesDelete partially complete.canceled=IF(LEN(A)>0,'no','yes')yesDelete canceled.failed=IF(LEN(A)>0,'no','yes')yesDelete failed.The formula in the disabled column uses
A(thejobIdalias).btnHardDeleteis set to a literalyes(always disabled) for all rows exceptcompleted, where it is set tono.
Test the Module
- Open the module in Preview.
- Enter a Start Date and End Date to define the range of records to delete.
- Click Delete Records to begin the soft delete.
- Click Refresh until the pop-up message reads
Records archived. Click Permanently Delete to remove them, or leave them archived. - 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. - To permanently remove the archived records, click Permanently Delete.
- Click Refresh again until the pop-up message updates to confirm the hard delete is complete.
Step 7 is irreversible. Only proceed if you are certain the archived records should be permanently removed.
Changelog
| Date | Change |
|---|---|
| 2026-10-06 | Set btnDelete and btnHardDelete Action to Validate; added Required ON to startDate and endDate; corrected startDate label from "created on/after" to "created after" to match exclusive API behavior; updated bundle to match. |
| 2026-10-06 | Full restructure from tested POC: added startDate/endDate Date Input components, corrected pluginHardDelete to use targetRecordType ARCHIVED and dynamic date fields, fixed URLs to bulkOperations (camelCase), per-component Configure sections, Inputs/Outputs tables, bundle download link. |
| 2026-09-30 | Initial publication. |