DELETE
Removes the target resource, with repeated calls producing the same end state.
What it does
DELETE removes the association between a target URI and a resource. Simple in concept, but the details matter: the spec doesn't require the server to physically destroy data — soft-deletes, archiving, or "hide from now on" behavior all satisfy DELETE's contract, as long as the resource is no longer accessible at that URI afterward.
Semantics
| Property | Value | Why it matters |
|---|---|---|
| Safe | No | Removes a resource |
| Idempotent | Yes | Deleting something already deleted has the same end state — it's gone either way |
| Cacheable | No | Not a read |
| Request body | Not typical | Some APIs allow one (e.g., bulk delete with a body), but it's non-standard and poorly supported by intermediaries |
| Response body | Optional | Often empty, sometimes a confirmation payload |
Syntax & example request
DELETE /orders/981 HTTP/1.1
Host: api.example.com
HTTP/1.1 204 No Content
curl example
curl -X DELETE https://api.example.com/orders/981
Common status codes returned
- 200 OK — deleted, response body has details → see 200
- 202 Accepted — delete queued for async processing → see 202
- 204 No Content — deleted, nothing more to say (most common) → see 204
- 404 Not Found — already gone, or never existed → see 404
DELETE and idempotency in practice
DELETE is idempotent in the sense that matters for retries: call it once, resource is gone. Call it again, resource is still gone — same end state. Where implementations disagree is the status code on the second call. Some return 204 again (silently no-op'ing on missing resources); others return 404 because, strictly, there's nothing left to delete. Both are defensible; pick one and document it, because clients need to know whether "404 on delete" means "network retry, all good" or "something's actually wrong."
Real-world usage
- Removing a specific resource:
DELETE /users/42 - Revoking access:
DELETE /sessions/{token},DELETE /api-keys/{id} - Bulk removal endpoints (non-standard, but common):
DELETE /orders?status=cancelled
Security considerations
DELETE needs the same authorization checks as any other write — verify the caller actually owns or can act on the resource being deleted, not just that they're authenticated. A frequent mistake is protecting the UI's delete button but leaving the underlying DELETE /resource/{id} endpoint checking only for a valid session, not the right one.
Because DELETE is destructive and idempotent, it's tempting to auto-retry on any failure — but be careful with soft-delete-then-hard-delete pipelines, since a delayed retry landing after a resource has been recreated (same ID, new data) can delete the wrong thing.
FAQ
Can DELETE have a request body?
Not by convention, and many proxies/frameworks strip it. If you need to delete based on complex criteria (not just an ID), a dedicated endpoint or query parameters are safer bets than relying on a DELETE body being honored end-to-end.
What should DELETE return on a resource that's already gone?
Either 204 No Content (idempotent no-op) or 404 Not Found (strictly accurate) — both are used in practice. Pick one, document it, and be consistent across your API.
Is a soft delete still a "real" DELETE?
Yes — the spec cares about the observable result (resource no longer accessible at that URI) not the storage mechanism. Archiving, flagging as deleted, or moving to a trash bin are all valid DELETE implementations as long as subsequent GETs 404 or otherwise reflect the removal.
Fun fact
DELETE has been part of HTTP since HTTP/1.1 (1997) — unlike GET/HEAD/POST, it wasn't in the original HTTP/1.0 spec, reflecting how early the web's founders assumed most interactions would be reads, with structured "remove this" semantics arriving once APIs (not just documents) became a serious use case.