Unqork documentation is available in two workspaces: UnqorkAI for the latest AI-first platform, and legacy Unqork for previous versions. Use the drop-down near the logo to switch.

Build a Bulk Delete Module

Prev Next

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 plugin prefix (for example, pluginExport) for clarity. The platform default for Plug-In components is plug — 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.

  1. Add an Initializer component to fgOnLoad.

  2. Configure the following settings:

    Setting Value
    Property ID initOnload
    Trigger 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.

  1. Add a Button component to fgUI.

  2. Configure the following settings:

    Setting Value
    Property ID btnRefresh
    Label Refresh
    Action Event
    Initial State Disabled
  3. 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.

  1. Add a Button component to fgUI after the Refresh button.

  2. Configure the following settings:

    Setting Value
    Property ID btnDelete
    Label Delete Records
    Action Validate
    Theme Danger
  3. 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.

  1. Add a Button component to fgUI after btnDelete.

  2. Configure the following settings:

    Setting Value
    Property ID btnHardDelete
    Label Permanently Delete
    Action Validate
    Theme Danger
    Initial State Disabled
  3. 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.

  1. Add a Date Input component to fgUI after the buttons.

  2. Configure the following settings:

    Setting Value
    Property ID startDate
    Label 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.

  1. Add a Date Input component to fgUI after startDate.

  2. Configure the following settings:

    Setting Value
    Property ID endDate
    Label 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.

  1. Add an Initializer component to fgConfig.

  2. Configure the following settings:

    Setting Value
    Property ID initError
    Trigger Type Manual
  3. Configure the Outputs:

    # Property ID Type Value
    1 response Value 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.

  1. Add a Plug-In component to fgConfig.

  2. Configure the following settings:

    Setting Value
    Property ID pluginDelete
    Trigger Type Manual
    Endpoint URL https://{environment}.unqork.io/fbu/uapi/bulkOperations/delete
    Method POST
  3. Configure the Inputs:

    # Property ID Value
    1 resourceId 'REPLACE_WITH_DATA_MODEL_ID'
    2 name 'Bulk Delete'
    3 dateFieldToFilterOn 'created'
    4 dateFieldStartToFilterOn startDate
    5 dateFieldEndToFilterOn endDate
  4. Configure the Outputs:

    # Property ID Value
    1 jobId id
  5. Under Triggers, set the Post Trigger drop-down to pluginGetJobDetails and the Error Handler drop-down to initError.

To delete records from a previous Export operation instead, set dataSource to 'EXPORT' and include exportOperationId as 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.

  1. Add a Plug-In component to fgConfig after pluginDelete.

  2. Configure the following settings:

    Setting Value
    Property ID pluginHardDelete
    Trigger Type Manual
    Endpoint URL https://{environment}.unqork.io/fbu/uapi/bulkOperations/delete?destroy=true
    Method POST
  3. 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 dateFieldStartToFilterOn startDate
    6 dateFieldEndToFilterOn endDate
  4. Configure the Outputs:

    # Property ID Value
    1 jobId id
  5. Under Triggers, set the Post Trigger drop-down to pluginGetJobDetails and the Error Handler drop-down to initError.

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.

  1. Add a Plug-In component to fgConfig after pluginHardDelete.

  2. Configure the following settings:

    Setting Value
    Property ID pluginGetJobDetails
    Trigger Type Manual
    Endpoint URL https://{environment}.unqork.io/fbu/uapi/bulkOperations/jobs/{{data.jobId}}
    Method
  3. Configure the Outputs:

    # Property ID Value
    1 status data.status
  4. 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.

  1. Add a Decisions component to fgConfig after pluginGetJobDetails.

  2. Configure the following settings:

    Setting Value
    Property ID ruleCheckStatus
    Trigger Type Manual
  3. Configure the Inputs:

    # Property ID Alias Type
    1 jobId A Exact
    2 status Exact
  4. Configure the Outputs:

    # Property ID Type
    1 btnRefresh Disabled
    2 btnHardDelete Disabled
    3 fgUI Pop Message
  5. Add one row per job status in the Decision grid:

    Status btnRefresh_disabled btnHardDelete_disabled fgUI_popMessage
    created =IF(LEN(A)>0,'no','yes') yes Delete started.
    inProgress =IF(LEN(A)>0,'no','yes') yes Delete in progress.
    completed =IF(LEN(A)>0,'no','yes') no Records archived. Click Permanently Delete to remove them, or leave them archived.
    partiallyCompleted =IF(LEN(A)>0,'no','yes') yes Delete partially complete.
    canceled =IF(LEN(A)>0,'no','yes') yes Delete canceled.
    failed =IF(LEN(A)>0,'no','yes') yes Delete failed.

    The formula in the disabled column uses A (the jobId alias). btnHardDelete is set to a literal yes (always disabled) for all rows except completed, where it is set to no.

Test the Module

  1. Open the module in Preview.
  2. Enter a Start Date and End Date to define the range of records to delete.
  3. Click Delete Records to begin the soft delete.
  4. Click Refresh until the pop-up message reads Records archived. Click Permanently Delete to remove them, or leave them archived.
  5. Open the submission using the platform's submission inspection method. See Debugger for how to access submission data from Express View.
  6. Confirm the jobId and status fields contain the expected values.
  7. To permanently remove the archived records, click Permanently Delete.
  8. 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.