Back to Payload

Trash

docs/trash/overview.mdx

3.84.16.7 KB
Original Source

Trash (also known as soft delete) allows documents to be marked as deleted without being permanently removed. When enabled on a collection, deleted documents will receive a deletedAt timestamp, making it possible to restore them later, view them in a dedicated Trash view, or permanently delete them.

Soft delete is a safer way to manage content lifecycle, giving editors a chance to review and recover documents that may have been deleted by mistake.

Collection Configuration

To enable soft deleting for a collection, set the trash property to true:

ts
import type { CollectionConfig } from 'payload'

export const Posts: CollectionConfig = {
  slug: 'posts',
  trash: true,
  fields: [
    {
      name: 'title',
      type: 'text',
    },
    // other fields...
  ],
}

When enabled, Payload automatically injects a deletedAt field into the collection's schema. This timestamp is set when a document is soft-deleted, and cleared when the document is restored.

Admin Panel behavior

Once trash is enabled, the Admin Panel provides a dedicated Trash view for each collection:

  • A new route is added at /collections/:collectionSlug/trash
  • The Trash view shows all documents that have a deletedAt timestamp

From the Trash view, you can:

  • Use bulk actions to manage trashed documents:

    • Restore to clear the deletedAt timestamp and return documents to their original state
    • Delete to permanently remove selected documents
    • Empty Trash to select and permanently delete all trashed documents at once
  • Enter each document's edit view, just like in the main list view. While in the edit view of a trashed document:

    • All fields are in a read-only state
    • Standard document actions (e.g., Save, Publish, Restore Version) are hidden and disabled.
    • The available actions are Restore and Permanently Delete.
    • Access to the API, Versions, and Preview views is preserved.

When deleting a document from the main collection List View, Payload will soft-delete the document by default. A checkbox in the delete confirmation modal allows users to skip the trash and permanently delete instead.

API Support

Soft deletes are fully supported across all Payload APIs: Local, REST, and GraphQL.

The following operations respect and support the trash functionality:

  • find
  • findByID
  • update
  • updateByID
  • delete
  • deleteByID
  • findVersions
  • findVersionByID

Understanding trash Behavior

Passing trash: true to these operations will include soft-deleted documents in the query results.

To return only soft-deleted documents, you must combine trash: true with a where clause that checks if deletedAt exists.

Examples

Local API

Return all documents including trashed:

ts
const result = await payload.find({
  collection: 'posts',
  trash: true,
})

Return only trashed documents:

ts
const result = await payload.find({
  collection: 'posts',
  trash: true,
  where: {
    deletedAt: {
      exists: true,
    },
  },
})

Return only non-trashed documents:

ts
const result = await payload.find({
  collection: 'posts',
  trash: false,
})

REST

Return all documents including trashed:

http
GET /api/posts?trash=true

Return only trashed documents:

http
GET /api/posts?trash=true&where[deletedAt][exists]=true

Return only non-trashed documents:

http
GET /api/posts?trash=false

GraphQL

Return all documents including trashed:

ts
query {
  Posts(trash: true) {
    docs {
      id
      deletedAt
    }
  }
}

Return only trashed documents:

ts
query {
  Posts(
    trash: true
    where: { deletedAt: { exists: true } }
  ) {
    docs {
      id
      deletedAt
    }
  }
}

Return only non-trashed documents:

ts
query {
  Posts(trash: false) {
    docs {
      id
      deletedAt
    }
  }
}

Access Control

All trash-related actions (soft delete, permanent delete, restore) respect the delete access control defined in your collection config.

This means:

  • If a user is denied delete access, they cannot soft delete or permanently delete documents

Differentiating Between Trash and Permanent Delete

You can configure access control to allow some users to trash documents while restricting permanent deletion to admins only. This is useful when you want editors to be able to "delete" content (move to trash) but only allow administrators to permanently remove data.

The delete access control function receives a data argument that contains the document data being set during the operation:

  • When trashing: data.deletedAt will be set to a timestamp
  • When permanently deleting: data will be undefined

This pattern is similar to how publish access control works with data._status.

Example: Allow All Users to Trash, Only Admins to Permanently Delete

ts
import type { CollectionConfig } from 'payload'

export const Posts: CollectionConfig = {
  slug: 'posts',
  trash: true,
  access: {
    delete: ({ req: { user }, data }) => {
      // Not logged in - no access
      if (!user) {
        return false
      }

      // Admins can do anything (trash or permanently delete)
      if (user.roles?.includes('admin')) {
        return true
      }

      // Regular users: check what operation they're attempting
      // If data.deletedAt is being set, it's a trash operation - allow it
      if (data?.deletedAt) {
        return true
      }

      // Otherwise it's a permanent delete - deny for non-admins
      return false
    },
  },
  fields: [
    // ...
  ],
}

Example: Only Admins Can Delete (Both Trash and Permanent)

ts
import type { CollectionConfig } from 'payload'

export const SensitiveData: CollectionConfig = {
  slug: 'sensitive-data',
  trash: true,
  access: {
    delete: ({ req: { user } }) => {
      // Only allow admins to trash or permanently delete
      return Boolean(user?.roles?.includes('admin'))
    },
  },
  fields: [
    // ...
  ],
}

In the Admin Panel, when a user has permission to trash but not permanently delete:

  • The delete button will be visible
  • The "Delete permanently" checkbox in the confirmation modal will be hidden
  • The user can only move documents to trash

Versions and Trash

When a document is soft-deleted:

  • It can no longer have a version restored until it is first restored from trash
  • Attempting to restore a version while the document is in trash will result in an error
  • This ensures consistency between the current document state and its version history

However, versions are still fully visible and accessible from the edit view of a trashed document. You can view the full version history, but must restore the document itself before restoring any individual version.