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 itemfilter_has_subitems: Filter items with/without children (with_subitems,without_subitems)filter_language: Filter by language codefilter_workflow_state: Filter by workflow statesort_by: Sorting options:date_desc(default) - Most recent firstdate_asc- Oldest firsttitle_asc/title_desc- Alphabetical by titletype_asc/type_desc- By content typepath_asc/path_desc- By pathsize_asc/size_desc- By sizeworkflow_asc/workflow_desc- By workflow state
Batching#
The API supports standard Plone REST API batching parameters:
b_start: Starting position for batchb_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