The HTTP specification also dictated that HTTP requests must contain a verb, and laid out rules for which verbs can be used for what types of request:
- GET: Requests the retrieval of a resource.
- POST: Requests where the server decides how to process the data. The URL specifies the resource that is to handle this request.
- PUT: Requests for the entity to be stored under the specified URL.
- PATCH: Requests for partial changes to be made to an existing resource.
- DELETE: Requests for the resource to be deleted.
- HEAD: Requests for the metadata of a resource.
- OPTIONS: Requests for information from the server regarding what requests are allowed.
Furthermore, GET, HEAD, OPTIONS, and TRACE are considered to be safe methods, which means they must not modify the representation of any resources. Other verbs, such as POST, PUT, and DELETE, are expected to modify resources and should be considered unsafe methods.
There's also the related concept of idempotency. An idempotent HTTP method is one that can be repeated multiple times but still produces the same outcome as if only a single request was sent. For example, DELETE is an idempotent method, because deleting a resource multiple times has the same effect as deleting it once. All safe methods are also idempotent:
| Method | Safe | Idempotent |
| CONNECT | ✗ | ✗ |
| DELETE | ✗ | ✓ |
| GET | ✓ | ✓ |
| HEAD | ✓ | ✓ |
| OPTIONS | ✓ | ✓ |
| POST | ✗ | ✗ |
| PUT | ✗ | ✓ |
| PATCH | ✗ | ✗ |
| TRACE | ✓ | ✓ |
Even if we conform to the HTTP specifications, there are still multiple ways to update a resource: using POST, PUT or PATCH. Therefore, when there is ambiguity in how to interpret a standard, we should turn to community consensus.
We are going to use a set of project guidelines published by Elsewhen, a digital product studio in London. It has over 17,500 stars on GitHub and can be accessed at github.com/elsewhencode/project-guidelines.
The part of the guidelines on HTTP methods is reproduced here:
- GET: To retrieve a representation of a resource.
- POST: To create new resources and sub-resources.
- PUT: To update existing resources.
- PATCH: To update existing resources. It only updates the fields that were supplied, leaving the others alone.
- DELETE: To delete existing resources.
So although we could update a resource by sending a POST request, we will limit POST requests only to the creation of resources.
Following the guidelines, we will also structure our API paths using the /<collection>/<id> structure, where <collection> is a class of resources (for instance, users, products, or articles), and <id> is the identifier for a particular resource within that collection (for instance, a particular user).
We will use plural nouns to name our collection to make the URL more consistent and easier to read. In other words, we will use /users and /users/<id>, instead of /user and /user/<id>.
Putting it all together, we get the following table, which details the actions that should be performed for each resource and HTTP method.
| Resource | GET | POST | PUT | PATCH | DELETE |
| /users | Retrieve a list of users | Create new user | Error | Error | Error |
| /users/<id> | Retrieve user | Error | Update user object (completely); error if user does not exists | Update user object (partially); error if user does not exists | Delete user object; error if user does not exists |