Restore or permanently delete from the recycle bin
Status: new. Deleting a datasource or data asset now moves it to the recycle bin instead of destroying it. Items are recoverable for
RECYCLE_BIN_RETENTION_DAYS(30 by default), then purged automatically.
Goal
You deleted a datasource or a data asset and want it back — or you want to destroy a binned item now rather than wait out the retention window. You'll list the recycle bin, restore an item, and (if needed) permanently purge one. See Recycle bin for the model of what gets binned and what is kept.
Prereqs
- To list, preview, or restore: an editor, workspace admin, or super admin role.
- To permanently purge: a workspace admin or super admin role.
- The item must still be in the bin. Once its
purge_atpasses (or someone purges it), it's gone and cannot be restored.
Background: how an item lands in the bin
- Deleting a datasource (editor and above) bins the data source, all its data assets, and each asset's rules — under one deletion group.
- Deleting a data asset (workspace admin and above) bins that asset and its rules.
- Shared objects are never binned. A validation that includes a binned asset keeps existing — it just stops running that asset's rules until you restore it. Results and agent tokens are all left in place.
- Execution runs and their results are always kept. The delete confirmation for a data source or a data asset lists what moves to the bin and says so, and so does the Delete permanently confirmation: a purge detaches the item's execution runs and results, it never deletes them. (Profile runs are different: they belong to the asset and go when it's purged.)
Steps
In the app, the Recycle bin page lists the same entries. Each row ends in two icon buttons: a circular-arrow Restore (editor+) and a red trash Delete permanently (workspace admin or super admin, behind a confirmation). Hover either one for a tooltip naming the action and the item. The steps below are the API equivalents.
-
List the bin.
GET /api/v2/organizations/{org_id}[/workspaces/{ws_id}]/recycle-bin. Each entry carriesresource_type(datasource/data_asset),id,name,deleted_at,purge_at, anddeletion_group_id. The list shows only top-level entries — an asset binned as part of a datasource delete rides under the datasource's entry, not its own row. The list is cursor-paginated newest-first: passlimitand roll the returnednext_cursorback in ascursorto page through (omitlimitfor the full set). -
(Optional) Preview before you act. For a live object you're about to delete,
GET .../recycle-bin/preview/datasource/{id}(or.../preview/data-asset/{id}) returns the blast radius: how many assets (and their rules), profile runs, anomaly events, and AI suggestions would be binned, how many validations would be kept (rule_groups_kept), and the retention window. The full count keys are listed in the API reference. -
Restore an item.
POST .../recycle-bin/datasources/{id}/restore(or.../data-assets/{id}/restore). The whole deletion group is un-tombstoned, so the object and everything owned under it reappears exactly where it was — assets back under the data source, each with its rules, and every validation that includes the asset runs its rules again. The response reports per-table restored-row counts.- Restoring an asset whose datasource is also binned returns
409. Restore the datasource first. If the asset and datasource were binned in the same delete, they share adeletion_group_id, so restoring the datasource brings the asset back with it. If the asset was binned independently and its datasource binned later (separate groups), restoring the datasource clears only its own group — the asset stays binned, so restore it afterward once it's the only binned member of its subtree.
- Restoring an asset whose datasource is also binned returns
-
(Optional) Purge early. If you're sure,
DELETE .../recycle-bin/datasources/{id}(or.../data-assets/{id}) hard-deletes the binned item's owned subtree right away. This is irreversible. Shared objects and the historical validation results are still preserved. Purge needs a workspace admin or super admin. -
Or do nothing. Left alone, an item is automatically purged once its
purge_at(i.e.deleted_at + RECYCLE_BIN_RETENTION_DAYS) passes. A daily worker cron at 03:45 UTC does the sweep.
Verify
- After a restore, the datasource or asset is back in its normal list and search; validations that include it run its rules again.
GET .../recycle-binno longer shows it. - After a purge (or automatic expiry), the item is gone from both the normal lists and the recycle bin. Its result history and any validations that included it are still present.
- Restores and purges are audit-logged — check
GET /api/v1/organizations/{org_id}/audit-eventsfor arestore/purgerow naming the object.
Create-vs-recycle-bin conflicts
A binned datasource or data asset is hidden from the normal lists — but its name is still taken. If you try to create a new object with the same identity while its twin is in the bin, the create is blocked so you don't end up with a hidden duplicate that surfaces the moment someone restores the bin entry.
-
Creating a datasource whose name matches a binned one, or a data asset whose
(datasource, name)matches a binned one, returns409with a body of{"detail": {"code": "binned_conflict", "message": "…is in the recycle bin. Restore it, or permanently delete it first.", "resource_type": …, "binned_id": …, "deletion_group_id": …}}. In the UI, the Add data source dialog offers Restore (editor+) or Purge permanently (workspace admin or super admin) inline — pick Restore to bring the original back, or Purge to free the name for a fresh create. -
Registering discovered tables (the Add N tables action in a source's Manage source window) does not fail the whole batch on a collision. Any table whose name matches a binned asset is skipped and reported back in the response's
conflicts[](each withname,binned_id,deletion_group_id); the modal shows an inline "In recycle bin — Restore" row for each. Fresh tables in the same batch still register normally. -
dbt ingestion auto-adopts. A dbt run that re-asserts a model whose asset is currently binned restores the binned asset (clears its tombstone) and refreshes it in place — counted as updated, with a
restoreaudit row. No manual step, no duplicate: your CI pipeline just re-adopts its own asset. -
Agent-registered datasources get the same
409 binned_conflictif the name is binned; restore or purge the twin from the recycle bin, then re-register.
Different workspaces are independent: a binned twin in workspace A never blocks — or is even visible to — a create in workspace B.
Related
- Recycle bin — the concept, the ownership rules, and the RBAC matrix.
- Datasources and Data assets — where the delete that fills the bin lives.
- Configuration → Worker —
RECYCLE_BIN_RETENTION_DAYS.