Soft Delete Resources


Hello, guys! There is common practice to delete resources to trash bin or archive on delete (to have an ability to restore them) and have additional force delete command to remove them completely from the database.

Imagine the situation when you want to delete task from the project management system, but it should be only marked as deleted, but kept as archived. And need an ability to restore it with the same id as it was before.

On DELETE /tasks/1 controller will execute soft-delete command and resource will update database column archived_at with current DateTime. Then resource will be excluded from all GET /tasks responses.

Why I’ve chosen to use DELETE method instead of updating status: archived field of the resource? Because there are a lot of cases when user shouldn’t know about resource is soft-deleted and will lose access to this record completely right after it’s soft-deletion. Only privileged users will have such permissions.

There are 2 questions which I’m trying to find answer to:

  1. How we could restore soft-deleted resource.
  2. How we could force delete resource.

This thread is related to “Should you return all resources by default (when no filter specified)” but not duplicates it, because it covers soft-delete, restore soft-delete and force-delete processes and not filtering strategy.

  1. I think you could simply update the status of an archived record to whatever it was before it was archived as a normal update operation.
  2. Delete a resource which is already archived, you can use ACL to check if someone can DELETE a resource in archived state just like you are restricting its display to some users.


What if I don’t want to acknowledge user that resource will be archived, not really deleted?


Well, I think the server can lie because from their perspective it is deleted. However if this is an end user facing application I would keep GDPR in mind when making this choice.


Thank you @michaelhibay. I agree, I should rethink this functionality somehow to make application more transparent.


Continuing the discussion from Soft Delete Resources:

  1. I completely agree that DELETE: can send a soft-delete. This would be transparent to the end user. No issues there at all.

  2. If you have permission to View, Restore & Remove the soft delete resources, there is not much to it at all. Handle it like any other resource. BECAUSE as far as this admin know, it is archived not delete.

This is very important when creating a Stateless API.

That all being said this user that has permission to restore the archived should be patching it.

  • You could patch archived_at : empty string or null or false.
  • You could patch no attributes at all to the resource. If the resource is archived_at and the ONLY valid change is to un-archive it. Then a patch with no attributes would un-archive it, as long as you have permission.
  1. If the user has permission to delete a resource permanently then they should be able to call delete on a resource that has been archived. Nothing strange about that.
  • first DELETE: always soft deletes
  • second DELETE: if the user does not have permission to hard delete this does nothing (404 not found) this resource does not exist to that user.
  • second DELETE: If the user has permission to hard delete then delete it successfully.


I would recommend keeping the DELETE method idempotent. There could be a race condition where a DELETE request is sent twice by someone who has permission to permanently delete the resource, even though their intention was to soft delete it. Perhaps adding an additional query parameter such as permanent=true might be safer.