Chapter 1 · Practice 3 of 4
Model operations that are not CRUD as sub-resources or state changes
From Resources and URLs
Why it matters
Some operations do not map neatly onto create, read, update and delete: cancelling an order, refunding a payment, resending an email. Two patterns keep them RESTful without inventing verbs in every path:
- A state change on the resource:
PATCH /orders/7with{"status": "cancelled"}, when the operation really is just a field change. - A sub-resource that represents the action or its result:
POST /payments/42/refundscreates a refund. The refund then has its own URL and history.
When neither fits, a clearly named action endpoint such as POST /orders/7/cancel is acceptable. Use POST for it, document it, and use the same pattern everywhere.
Example
POST /payments/42/refunds
Content-Type: application/json
{ "amount": "15.00", "currency": "USD", "reason": "damaged_item" }
HTTP/1.1 201 Created
Location: /payments/42/refunds/9