Skip to main content

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_at passes (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.

  1. List the bin. GET /api/v2/organizations/{org_id}[/workspaces/{ws_id}]/recycle-bin. Each entry carries resource_type (datasource / data_asset), id, name, deleted_at, purge_at, and deletion_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: pass limit and roll the returned next_cursor back in as cursor to page through (omit limit for the full set).

  2. (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.

  3. 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 a deletion_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.
  4. (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.

  5. 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-bin no 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-events for a restore / purge row 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, returns 409 with 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 with name, 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 restore audit row. No manual step, no duplicate: your CI pipeline just re-adopts its own asset.

  • Agent-registered datasources get the same 409 binned_conflict if 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.