Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

REST pattern create, update and delete same endpoint

Tags:

rest

I have a page where I list the books of a school. The user can update a book, add a new book or delete an existing book. All actions must be saved when the form is submitted.

How can i map a rest API for that? I could take advantage of the endpoints i already have.

UPDATE

PUT /schools/1/books
{
  "books": [
    {
      "id": "1",
      "name": "Book 1"
    }
  ]
}

CREATE

POST /schools/1/books
{
  "books": [
    {
      "name": "Book 2"
    },
    {
      "name": "Book 3"
    }
  ]
}

DELETE

DELETE /schools/1/books
{
  "books": [
    {
      "id": 2
    }
  ]
}

But I need everything to run on the same transaction, and wouldn't make sense to submit 3 requests.

I also thought of creating a new endpoint where I would create books that doesn't exists, update books that exists, and remove books that are not present on the request.

So if this school has Book 1 and Book 2, I could update Book 1, create New Book and remove Book 2 with:

PUT /schools/1/batch-books
{
  "books": [
    {
      "id": "1",
      "name": "Updated Book 1"
    },
    {
      "name": "New Book"
    }
  ]
}

Do you guys have other options?

like image 906
Guilherme Miranda Avatar asked Mar 24 '26 04:03

Guilherme Miranda


1 Answers

I would separate things into different resources:

  • /books and /books/{id} for books. They gives book details and allow to manage them.
  • /schools and /schools/{id} for schools. They gives school details and allow to manage them.
  • /schools/{id}/books to associate books in schools. I mean books that are available within a school. This resource provides methods to manage a list of links to books.

Let me detail the last resource. In fact, this is related to hypermedia. In the following, I'll use JSON-LD but you're free to use other hypermedia tools.

A GET method will return the list of associated books:

GET /schools/1/books
[
  {
    "@id": "http://api.example.com/books/1895638109"
  },
  {
    "@id": "http://api.example.com/books/8371023509"
  }
]

You can notice that you can implement mechanisms to allow to get more details if needed. Leveraging the Prefer header seems to be a great approach (see the link below for more details).

In addition, you could provide the following methods:

  • POST to add a link to the school. The request payload would be: {"@id": "http://api.example.com/books/1895638109"}. The response should be a 201 status code.

  • DELETE to delete a specific link from a school. A query parameter could be used to specify which link to remove.

  • PATCH to allow to do several operations in one call and actually provide some batch processing. You can leverage at this level JSON-PATCH for the request processing. Within the response, you could describe what happens. There is no specification at this level so you're free to use what you want... Here is a sample for the request payload:

      PATCH /schools/1/books/
      [
        {
          "op": "add", "value": "http://api.example.com/books/1895638109"
        },
        {
          "op": "remove", "path": "http://api.example.com/books/8371023509"
        }
      ]
    

Reading the following links could give you some hints on the way to design such use case:

  • Implementing bulk updates within RESTful services: http://restlet.com/blog/2015/05/18/implementing-bulk-updates-within-restful-services/
  • On choosing a hypermedia type: http://sookocheff.com/post/api/on-choosing-a-hypermedia-format/
  • Creating Client-Optimized Resource Representations in APIs: http://www.freshblurbs.com/blog/2015/06/25/api-representations-prefer.html

Hope it helps you, Thierry

like image 111
Thierry Templier Avatar answered Mar 26 '26 09:03

Thierry Templier



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!