Recycle Bin#

The Recycle Bin REST API provides endpoints to interact with the Plone Recycle Bin functionality.

Reading or writing recycle bin data requires the cmf.ManagePortal permission.

List recycle bin contents#

A list of all items in the recycle bin can be retrieved by sending a GET request to the @recyclebin endpoint:

http

GET /plone/@recyclebin HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0

curl

curl -i -X GET http://nohost/plone/@recyclebin -H "Accept: application/json" --user admin:secret

httpie

http http://nohost/plone/@recyclebin Accept:application/json -a admin:secret

python-requests

requests.get('http://nohost/plone/@recyclebin', headers={'Accept': 'application/json'}, auth=('admin', 'secret'))
HTTP/1.1 200 OK
Content-Type: application/json

{
    "@id": "http://localhost:55001/plone/@recyclebin",
    "items": [
        {
            "@id": "http://localhost:55001/plone/@recyclebin/6c952845-d878-4301-892b-2c7e8a24323a",
            "actions": {
                "purge": "http://localhost:55001/plone/@recyclebin/6c952845-d878-4301-892b-2c7e8a24323a",
                "restore": "http://localhost:55001/plone/@recyclebin/6c952845-d878-4301-892b-2c7e8a24323a/restore"
            },
            "deleted_by": "test_user_1_",
            "deletion_date": "2025-10-08T04:23:14.793653",
            "has_children": false,
            "id": "document1",
            "language": "",
            "parent_path": "/plone",
            "path": "/plone/document1",
            "recycle_id": "6c952845-d878-4301-892b-2c7e8a24323a",
            "size": 0,
            "title": "My Document",
            "type": "Document",
            "workflow_state": "private"
        },
        {
            "@id": "http://localhost:55001/plone/@recyclebin/74202eb6-403b-4c5c-910f-55b399f75ee7",
            "actions": {
                "purge": "http://localhost:55001/plone/@recyclebin/74202eb6-403b-4c5c-910f-55b399f75ee7",
                "restore": "http://localhost:55001/plone/@recyclebin/74202eb6-403b-4c5c-910f-55b399f75ee7/restore"
            },
            "deleted_by": "test_user_1_",
            "deletion_date": "2025-10-08T04:23:14.788751",
            "has_children": true,
            "id": "folder1",
            "language": "",
            "parent_path": "/plone",
            "path": "/plone/folder1",
            "recycle_id": "74202eb6-403b-4c5c-910f-55b399f75ee7",
            "size": 0,
            "title": "My Folder",
            "type": "Folder",
            "workflow_state": "private"
        },
        {
            "@id": "http://localhost:55001/plone/@recyclebin/1d55485a-c26d-457d-a89c-f125ea041da6",
            "actions": {
                "purge": "http://localhost:55001/plone/@recyclebin/1d55485a-c26d-457d-a89c-f125ea041da6",
                "restore": "http://localhost:55001/plone/@recyclebin/1d55485a-c26d-457d-a89c-f125ea041da6/restore"
            },
            "deleted_by": "test_user_1_",
            "deletion_date": "2025-10-08T04:23:14.785316",
            "has_children": false,
            "id": "subdoc",
            "language": "",
            "parent_path": "/plone",
            "path": "/plone/folder1/subdoc",
            "recycle_id": "1d55485a-c26d-457d-a89c-f125ea041da6",
            "size": 0,
            "title": "Sub Document",
            "type": "Document",
            "workflow_state": "private"
        }
    ],
    "items_total": 3
}

Filtering and Sorting Parameters#

The listing supports various query parameters for filtering and sorting:

  • search_query: Search in title and path (case-insensitive)

  • filter_type: Filter by content type (e.g., "Document", "Folder")

  • date_from: Filter by deletion date from (YYYY-MM-DD format)

  • date_to: Filter by deletion date to (YYYY-MM-DD format)

  • filter_deleted_by: Filter by user who deleted the item

  • filter_has_subitems: Filter items with/without children (with_subitems, without_subitems)

  • filter_language: Filter by language code

  • filter_workflow_state: Filter by workflow state

  • sort_by: Sorting options:

    • date_desc (default) - Most recent first

    • date_asc - Oldest first

    • title_asc / title_desc - Alphabetical by title

    • type_asc / type_desc - By content type

    • path_asc / path_desc - By path

    • size_asc / size_desc - By size

    • workflow_asc / workflow_desc - By workflow state

Batching#

The API supports standard Plone REST API batching parameters:

  • b_start: Starting position for batch

  • b_size: Number of items per batch

Example with filtering and sorting#

http

GET /plone/@recyclebin?filter_type=Document&sort_by=title_asc HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0

curl

curl -i -X GET 'http://nohost/plone/@recyclebin?filter_type=Document&sort_by=title_asc' -H "Accept: application/json" --user admin:secret

httpie

http 'http://nohost/plone/@recyclebin?filter_type=Document&sort_by=title_asc' Accept:application/json -a admin:secret

python-requests

requests.get('http://nohost/plone/@recyclebin?filter_type=Document&sort_by=title_asc', headers={'Accept': 'application/json'}, auth=('admin', 'secret'))
HTTP/1.1 200 OK
Content-Type: application/json

{
    "@id": "http://localhost:55001/plone/@recyclebin?filter_type=Document&sort_by=title_asc",
    "items": [
        {
            "@id": "http://localhost:55001/plone/@recyclebin/56a3e44a-f095-4027-a76e-7084059dd5dd",
            "actions": {
                "purge": "http://localhost:55001/plone/@recyclebin/56a3e44a-f095-4027-a76e-7084059dd5dd",
                "restore": "http://localhost:55001/plone/@recyclebin/56a3e44a-f095-4027-a76e-7084059dd5dd/restore"
            },
            "deleted_by": "test_user_1_",
            "deletion_date": "2025-10-08T04:23:15.024785",
            "has_children": false,
            "id": "document1",
            "language": "",
            "parent_path": "/plone",
            "path": "/plone/document1",
            "recycle_id": "56a3e44a-f095-4027-a76e-7084059dd5dd",
            "size": 0,
            "title": "My Document",
            "type": "Document",
            "workflow_state": "private"
        },
        {
            "@id": "http://localhost:55001/plone/@recyclebin/771d4daf-6282-42a3-a09f-9c9fcd1265f6",
            "actions": {
                "purge": "http://localhost:55001/plone/@recyclebin/771d4daf-6282-42a3-a09f-9c9fcd1265f6",
                "restore": "http://localhost:55001/plone/@recyclebin/771d4daf-6282-42a3-a09f-9c9fcd1265f6/restore"
            },
            "deleted_by": "test_user_1_",
            "deletion_date": "2025-10-08T04:23:15.015428",
            "has_children": false,
            "id": "subdoc",
            "language": "",
            "parent_path": "/plone",
            "path": "/plone/folder1/subdoc",
            "recycle_id": "771d4daf-6282-42a3-a09f-9c9fcd1265f6",
            "size": 0,
            "title": "Sub Document",
            "type": "Document",
            "workflow_state": "private"
        }
    ],
    "items_total": 2
}

Get individual item from recycle bin#

To retrieve detailed information about a specific item in the recycle bin, send a GET request to @recyclebin/{item_id}:

http

GET /plone/@recyclebin/700e304f-248a-40bb-88de-61f1f52c992d HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0

curl

curl -i -X GET http://nohost/plone/@recyclebin/700e304f-248a-40bb-88de-61f1f52c992d -H "Accept: application/json" --user admin:secret

httpie

http http://nohost/plone/@recyclebin/700e304f-248a-40bb-88de-61f1f52c992d Accept:application/json -a admin:secret

python-requests

requests.get('http://nohost/plone/@recyclebin/700e304f-248a-40bb-88de-61f1f52c992d', headers={'Accept': 'application/json'}, auth=('admin', 'secret'))
HTTP/1.1 503 Service Unavailable
Content-Type: application/json

{
    "context": "http://localhost:55001/plone",
    "message": "'recycle_id'",
    "traceback": [
        "File \"/home/rohnsha0/code/buildout.coredev/eggs/v5/Zope-5.13-py3.13-linux-x86_64.egg/ZPublisher/WSGIPublisher.py\", line 181, in transaction_pubevents",
        "    yield",
        "",
        "  File \"/home/rohnsha0/code/buildout.coredev/eggs/v5/Zope-5.13-py3.13-linux-x86_64.egg/ZPublisher/WSGIPublisher.py\", line 390, in publish_module",
        "    response = _publish(request, new_mod_info)",
        "",
        "  File \"/home/rohnsha0/code/buildout.coredev/eggs/v5/Zope-5.13-py3.13-linux-x86_64.egg/ZPublisher/WSGIPublisher.py\", line 284, in publish",
        "    result = mapply(obj,",
        "                    request.args,",
        "    ...<5 lines>...",
        "                    request,",
        "                    bind=1)",
        "",
        "  File \"/home/rohnsha0/code/buildout.coredev/eggs/v5/Zope-5.13-py3.13-linux-x86_64.egg/ZPublisher/mapply.py\", line 98, in mapply",
        "    return debug(object, args, context)",
        "",
        "  File \"/home/rohnsha0/code/buildout.coredev/eggs/v5/Zope-5.13-py3.13-linux-x86_64.egg/ZPublisher/WSGIPublisher.py\", line 68, in call_object",
        "    return obj(*args)",
        "",
        "  File \"/home/rohnsha0/code/buildout.coredev/eggs/v5/plone.rest-5.1.0-py3.13-linux-x86_64.egg/plone/rest/service.py\", line 21, in __call__",
        "    return self.render()",
        "           ~~~~~~~~~~~^^",
        "",
        "  File \"/home/rohnsha0/code/buildout.coredev/src/plone.restapi/src/plone/restapi/services/__init__.py\", line 19, in render",
        "    content = self.reply()",
        "",
        "  File \"/home/rohnsha0/code/buildout.coredev/src/plone.restapi/src/plone/restapi/services/recyclebin/get.py\", line 39, in reply",
        "    return self._reply_individual_item(recycle_bin)",
        "           ~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^",
        "",
        "  File \"/home/rohnsha0/code/buildout.coredev/src/plone.restapi/src/plone/restapi/services/recyclebin/get.py\", line 71, in _reply_individual_item",
        "    \"@id\": f\"{self.context.absolute_url()}/@recyclebin/{item['recycle_id']}\",",
        "                                                        ~~~~^^^^^^^^^^^^^^"
    ],
    "type": "KeyError"
}

Restore an item from the recycle bin#

An item can be restored from the recycle bin by issuing a POST to the given URL:

http

POST /plone/@recyclebin/dc187392-0882-427b-aa11-eae7ce5d1e54/restore HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0

curl

curl -i -X POST http://nohost/plone/@recyclebin/dc187392-0882-427b-aa11-eae7ce5d1e54/restore -H "Accept: application/json" --user admin:secret

httpie

http POST http://nohost/plone/@recyclebin/dc187392-0882-427b-aa11-eae7ce5d1e54/restore Accept:application/json -a admin:secret

python-requests

requests.post('http://nohost/plone/@recyclebin/dc187392-0882-427b-aa11-eae7ce5d1e54/restore', headers={'Accept': 'application/json'}, auth=('admin', 'secret'))
HTTP/1.1 200 OK
Content-Type: application/json

{
    "message": "Item document1 restored successfully",
    "restored_item": {
        "@id": "http://localhost:55001/plone/document1",
        "id": "document1",
        "title": "My Document",
        "type": "Document"
    },
    "status": "success"
}

Restore to specific target location#

You can specify a target path to restore the item to a different location than its original:

http

POST /plone/@recyclebin/d440fbb4-9b70-437f-b1d4-a86172724955/restore HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0
Content-Type: application/json

{
    "target_path": "/plone/target_folder"
}

curl

curl -i -X POST http://nohost/plone/@recyclebin/d440fbb4-9b70-437f-b1d4-a86172724955/restore -H "Accept: application/json" -H "Content-Type: application/json" --data-raw '{"target_path": "/plone/target_folder"}' --user admin:secret

httpie

echo '{
  "target_path": "/plone/target_folder"
}' | http POST http://nohost/plone/@recyclebin/d440fbb4-9b70-437f-b1d4-a86172724955/restore Accept:application/json Content-Type:application/json -a admin:secret

python-requests

requests.post('http://nohost/plone/@recyclebin/d440fbb4-9b70-437f-b1d4-a86172724955/restore', headers={'Accept': 'application/json', 'Content-Type': 'application/json'}, json={'target_path': '/plone/target_folder'}, auth=('admin', 'secret'))
HTTP/1.1 200 OK
Content-Type: application/json

{
    "message": "Item document2 restored successfully",
    "restored_item": {
        "@id": "http://localhost:55001/plone/target_folder/document2",
        "id": "document2",
        "title": "Another Document",
        "type": "Document"
    },
    "status": "success"
}

Purge a specific item from the recycle bin#

To permanently delete a specific item from the recycle bin, send a DELETE request to the @recyclebin/{item_id} endpoint:

http

DELETE /plone/@recyclebin/c15a7588-fe0e-49a2-9fe6-3356b6962150 HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0

curl

curl -i -X DELETE http://nohost/plone/@recyclebin/c15a7588-fe0e-49a2-9fe6-3356b6962150 -H "Accept: application/json" --user admin:secret

httpie

http DELETE http://nohost/plone/@recyclebin/c15a7588-fe0e-49a2-9fe6-3356b6962150 Accept:application/json -a admin:secret

python-requests

requests.delete('http://nohost/plone/@recyclebin/c15a7588-fe0e-49a2-9fe6-3356b6962150', headers={'Accept': 'application/json'}, auth=('admin', 'secret'))
HTTP/1.1 204 No Content

Empty the entire recycle bin#

To permanently delete all items from the recycle bin, send a DELETE request to the @recyclebin endpoint:

http

DELETE /plone/@recyclebin HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0

curl

curl -i -X DELETE http://nohost/plone/@recyclebin -H "Accept: application/json" --user admin:secret

httpie

http DELETE http://nohost/plone/@recyclebin Accept:application/json -a admin:secret

python-requests

requests.delete('http://nohost/plone/@recyclebin', headers={'Accept': 'application/json'}, auth=('admin', 'secret'))
HTTP/1.1 204 No Content