Rest – Design: Update properties on an entity in a RESTful, resource-based, API

apiapi-designdesignrest

I am working on a RESTful, resource-based, API and I have a large entity (an account) with a lot of properties (30, we'll say). The account has a couple of properties that can be changed…

  1. Name: This actually submits a request (e-mail) for a person to confirm the identity and they use a separate system to update the name.

  2. Target Savings Amount: It's just a number that the client can update to be whatever they want.

So, here's my thoughts were, and why I don't like them:

1. Merge PATCH

  • PATCH …/account/{id}

I would take an account entity in the patch body and update what has changed… which in this case can only be 2 properties (name/savings-target) and 422 any other changes.

  • I like it because you can GET>Modify>PATCH very seamlessly.
  • I don't like it because of such a small change surface for a merge patch doesn't make a tonne of sense. Updating name and savings-target at the same time ends up in an ambiguous response as the name update doesn't take effect.

2. POST updates

  • POST …/account/{id}/updates/name?value=test
  • POST …/account/{id}/updates/savings-target?value=123.00

Treat updates as entities and post new ones to the account.

  • I like it because it's consistent, clean, allows me to handle responses differently (name update returns some kind of deferred response like a 204 or something, and a 200 for savings-target).
  • I don't like it because it feels like it's falling into an RPC-esque API and I'm trying to avoid that. Treating updates as entities seems janky as there's no updates to GET. Also, if I do end up adding more fields that can be updated, this gets ugly really fast.

3. Actual Update Entities

  • POST …/account/{id}/updates
    • takes a body that is probably just a key/value pair and returns 303 referring to to…
  • GET …/account/{id}/updates/{update-id}
  • GET …/account/{id}/updates
    • also a valid endpoint that could return all of the updates created for this account entity

Basically, 2, but I have actual entities for updates a-la CQRS. The update entity (for lack of a better name, at the moment) has a status indicating whether the change has been completed.

  • I like it because it models the changes most accurately, I think.
  • I don't like it because it's a heavyweight solution. For trivial changes like the savings-target, I can update the account entity and complete the update entity immediately which is fine, but for something like name, there's no system in place to actually call back to the update entity to complete it.

It seems like a boat load of overkill, and a lot of work just to have a cleaner API. I also don't have the throughput concerns that normally warrant that type of architecture.

4. JSON Patch

As seen here

  • I like it because it's a standard and is relatively easy to implement.
  • I don't like it because it goes against the resource-based focus of the API that I'm developing (this is a requirement from the business…).

Help

I'm not constrained to these 4 choices, but they're the best ones I could think of. I'm leaning towards 2 and am looking to be either validated, or given an experience-based solution from someone else who's encountered a similar situation.

Best Answer

Consider using micro endpoints. You can expose the following additional endpoints:

/accounts/{id}/name
/accounts/{id}/savings-target

You can enable POST on the name and PUT on the target savings amount. You don't even need to support JSON on the endpoints. You can POST to name a simple string (email address), and you can PUT the new target amount. The account endpoint response can still include the name and savings-target properties.

Related Topic