2

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.

2

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.

  • I had thought of that and the concern I had was that name/savings-target are not entities within the domain (they're just properties on the account entity) but are being modeled that way using endpoints like this. – Steven Evers May 21 '18 at 20:16
  • @StevenEvers ReSTful APIs don't expose entities. They expose "resources". A resource can be whatever you need it to be. – Eric Stein May 21 '18 at 23:27
  • Fair enough, I misspoke. name/savings-target are not resources, and if I model them as such then it feels like I'm so loosely defining "resources" that the term loses value for the purpose of designing the API, and "everything's a resource and it's all just endpoints" again. I might be wrong. What do you think? – Steven Evers May 24 '18 at 18:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.