What is the standard practice for designing REST API if it is being used for inserting / updating a list of records

1.1k Views Asked by At

We are building an API which will be used for inserting and updating the records in a database. So if the record exists based on the Key the record will be updated and if it does not then it will be inserted.

I have two questions.

  • As per REST guidelines, what are the options for designing such an API e.g. PUT / POST OR PATCH? How should the list of objects be represented? NOTE: I know from other answers that I read that there is confusion over how it should be as per REST guidelines. So I am OK if I can get some guidance on general best practice (irrespective of REST part)
  • Secondly, the part where I am really confused about is how to represent the output of this or what this API should return.

Specific guidance/inputs on above topic would be really appreciated.

1

There are 1 best solutions below

5
Mo A On

I've seen many different implementations for inserts/updates across various vendors (Stripe, HubSpot, PayPal, Google, Microsoft). Even though they differ, the difference somehow fits well with their overall API implementation and is not usually a cause for stress.


With that said, the "general" rule for inserts is:

POST /customers - provide the customer details within the body.

This will create a new customer, returns the unique ID and customer details in the response (along with createdDate and other auto-generated attributes).

Pretty much most, if not all API vendors, implement this logic for inserts.


Updates, are quite different. Your options include:

POST

POST /customer/<customer_id> - include attributes and values you want to update within the body.

Here you use a POST to update the customer. It's not a very common implementation, but I've seen it in several places.

PUT

PUT/customer/<customer_id> - include either all, or partially updated attributes within the body.

Given PUT is technically an idempotent method, you can either stay true to the REST convention and expect your users to provide all the attributes to update the resource, or make it simpler by only accepting the attributes they want to update. The second option is not very "RESTful", but is easier to handle from a users perspective (and reduces the size of the payload).

PATCH

PATCH /customer/<customer_id> - include the operation and attributes that you want to update / remove/ replace / etc within the body. More about how to PATCH.

The PATCH method is used for partial updates, and it's how you're "meant" to invoke partial updates. It's a little harder to use from a consumers perspective.

Now, this is where the bias kicks-in. I personally prefer to use POST, where I am not required to provide all the attributes to invoke an update (just the ones I want to update). Reason is due to simplicity of usage.

In terms of the response body for the updates, usually they will return object within the response body include the updated attributes (and updated auto-generated attributes, such updatedDate).


Bulk inserts/ updates

Looking at the Facebook Graph HTTP API (Batch Request) for inspiration, and assuming POST is your preferred method for updates, you could embed an array of requests using a dedicated batch resource as an option.

Endpoint: POST /batch/customers

Body:

{
   ["first_name": "John", "last_name": "Smith"...], //CREATE
   ["id": "777", "first_name": "Jane", "last_name": "Doe"...], //UPDATE
   ["id": "999", "first_name": "Mike", "last_name": "Smith"...], //UPDATE
   [....]
}

Sample Response

{
  "id": "123",
  "result":[
      { // Creation successful
        "code": 200,
        "headers":{..},
        "body": {..},
        "uri": "/customers/345"
      },
      { // Update successful
        "code": 200,
        "headers":{..},
        "body": {..},
        "uri": "/customers/777",
      },
      { // A failed update request
        "code": 404,
        "headers":{..},
        "body": {..}, // body includes error details
      }
  ]
}