---
type: practical
---
- [Updating information](#Updating%20information)
	- [The existence of the `PATCH` request](#The%20existence%20of%20the%20%60PATCH%60%20request)
	- [Usage of `PUT`](#Usage%20of%20%60PUT%60)
		- [Complete request example](#Complete%20request%20example)
		- [Incomplete request example](#Incomplete%20request%20example)
	- [Usage of `POST`](#Usage%20of%20%60POST%60)
- [General "style" remarks](#General%20%22style%22%20remarks)
- [Conclusion / TL;DR](#Conclusion%20/%20TL;DR)

## Updating information
Can we have optional fields in the update `PUT` and `POST` request?

### The existence of the `PATCH` request 
>The **`PATCH`** HTTP method applies partial modifications to a resource.
>`PATCH` is somewhat analogous to the "update" concept found in [CRUD](https://developer.mozilla.org/en-US/docs/Glossary/CRUD) (in general, HTTP is different than [CRUD](https://developer.mozilla.org/en-US/docs/Glossary/CRUD), and the two should not be confused).[^1]


Hence, this definition also answers the question as to why we **should be careful with the usage of  `PATCH`** if we consider it.

### Usage of `PUT`
>The PUT method requests that the state of the target resource be
   created or replaced with the state **defined by the representation**
   **enclosed in the request message payload**. [^3]

This implies that complete resource representation **is required** (all the fields), as Jackson(Spring) will reset the missing ones to their default values (e.g. int = 0, boolean = false, String = null, etc.)


#### Complete request example

*Request:*
```json
{
  "isbn": "978-3-16-148410-0",
  "name": "Among us story",
  "author": "Yo mama",
  "genre": "Horror",
  "publisher": "Team 22",
  "publishDate": "2023-09-01",
  "pages": 320
}

```

*Response:*
```json
<<< 200 OK
{
  "isbn": "978-3-16-148410-0",
  "name": "Among us story",
  "author": "Yo mama",
  "genre": "Horror",
  "publisher": "Team 22",
  "publishDate": "2023-09-01",
  "pages": 320
}

```

#### Incomplete request example
(this is assuming the above request happened already)
*Request:*
```json
{
  "isbn": "978-3-16-148410-0",
  "name": "Among us story",

  
  "publisher": "Team 22",
  
  "pages": 320
}
```

*Response*:
```json

<<< 200 OK
{
  "isbn": "978-3-16-148410-0",
  "name": "Among us story",
  "author": null,
  "genre": null,
  "publisher": "Team 22",
  "publishDate": null,
  "pages": 320
}
```
### Usage of `POST`
Contrary to `PUT`:
>The `POST` method is **used to request that the target resource process the enclosed representation according to the resource's own specific semantics**. The meaning of a `POST` request is determined by the server and is usually dependent on the resource identified by the Request-URI.[^4]

Therefore we *can* send requests which contain data that are non-complete resource representations. We do have to explain this to the other team tho...

i.e.
*Request:*
```json
{
  "isbn": "978-3-16-148410-0"
}
```

*Response:*
``` json
<<< 201 Created
{
  "isbn": "978-3-16-148410-0",
  "name": null,
  "author": null,
  "genre": null,
  "publisher": null,
  "publishDate": null,
  "pages": 0
}


``` 

## General "style" remarks
(based on the API conventions + CRUD principle)
>The base URL should be neat, elegant, and simple so that developers using your product can easily use them in their web applications. A long and difficult-to-read base URL is not just bad to look at, but can also be prone to mistakes when trying to recode it. Nouns should always be trusted.[^2]

Hence, using a verb in `POST /api/v1/book/create` and `PUT /api/v1/book/update` is not ideal.

Table[^2] of common conventions for the usage of HTTP requests:



| **Resource**        | `POST`                            | `GET`                               | `PUT`                                         | `DELETE`                         |
| ------------------- | --------------------------------- | ----------------------------------- | --------------------------------------------- | -------------------------------- |
| /customers          | Create a new customer             | Retrieve all customers              | Bulk update of customers                      | Remove all customers             |
| /customers/1        | Error                             | Retrieve the details for customer 1 | Update the details of customer 1 if it exists | Remove customer 1                |
| /customers/1/orders | Create a new order for customer 1 | Retrieve all orders for customer 1  | Bulk update of orders for customer 1          | Remove all orders for customer 1 |

Hence, in our case:

| **Resource**  | `POST`            | `GET`                                                    | `PUT`                                            | `DELETE`                |
| ------------- | ----------------- | -------------------------------------------------------- | ------------------------------------------------ | ----------------------- |
| /books        | Create a new book | Retrieve all books (+ optional parameters for filtering) | 405                                              | Remove all books        |
| /books/{isbn} | 405               | Retrieve the details for book with `isbn`                | Update the details of book with `isbn` if exists | Remove book with `isbn` |



## Conclusion / TL;DR
Given the information provided above, I propose we change the current specification as follows:

| Method   | Old URL/Description                                                                                  | New URL/Description                                                                                            | Reasoning                                                                                                                      |
| -------- | ---------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `POST`   | `/api/v1/book/create` - Create book - pass JSON body (isbn is required)                              | `/api/v1/books` - Create a book - pass JSON body (isbn is required)                                            | Use resource-based naming convention (`books` as a collection). HTTP POST implies creation; no need for `/create`.             |
| `PUT`    | `/api/v1/book/update` - Update book - pass JSON body (isbn is required)                              | `/api/v1/books/{isbn}` - Update a specific book - pass JSON body                                               | Use path parameter (`{isbn}`) to specify which book to update. HTTP PUT implies updating a specific resource.                  |
| `GET`    | `/api/v1/book?genre={genre}&author={author}&data="csv"` - Get book(s) by property in csv/json format | `/api/v1/books?genre={genre}&author={author}` - Get books by property. Use `Accept` header for csv/json format | Use plural `books` for collections. Use HTTP `Accept` header for content negotiation (CSV/JSON), keeping URLs clean.           |
| `DELETE` | `/api/v1/book?genre={genre}&author={author}` - Delete book(s) by property                            | `/api/v1/books` - Delete books - pass filter criteria in body or delete one by `/api/v1/books/{isbn}`          | `DELETE` requests with body for filtering criteria, or use path param for deleting a single resource for better clarity.       |
| `POST`   | `/api/v1/book/import?data="csv"` - Import books from csv/json file (isbn is required for each)       | `/api/v1/books/import` - Import books from CSV/JSON file - pass file in body; use `Content-Type` header        | Use resource-based naming (`books/import`). The `Content-Type` header indicates file type (CSV/JSON); keep query params clean. |



[^1]: [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH)
[^2]: [Swagger](https://swagger.io/resources/articles/best-practices-in-api-design/)
[^3]: [RFC 7231 - PUT](https://datatracker.ietf.org/doc/html/rfc7231#autoid-37)
[^4]: [RFC 7231 - POST](https://datatracker.ietf.org/doc/html/rfc7231#autoid-36)