I work in the SAP industry where web-based UIs and RESTful APIs are a rather new thing, meaning some teams (like ours) don’t have much experience in designing such systems. Recently there’s been a dicussion that revolved about whether our API should be an abstract representation of the resource or client-specific by pre-filtering a subset of the resource. Let me try to elaborate using the specific use case that was the center of the discussion:
Say we have a business object work-task
that has a property called status
. That status may have several values, say active
and closed
. Now, a web-based UI is being designed that allows users to edit work-tasks, but only if they have the status active
.
Before I explain the two opinions on how to design the API, let me state some important prerequisites:
- The validation whether a
work-task
can be edited (the status check) is always done on the server during UPDATE
.
- There will likely come the requirement to develop different clients that e.g. require
work-task
regardless of status
- There are no security concerns regarding the
status
property being visible to the user
These are the two opinions on how to approach this (I obviously have a clear preference, but I’m going to try to recite both to the best of my abilities):
- Design an abstract API and allow the client to filter for
status='active'
in the query. The goal is to make the API easily reusable. That includes that the client developer needs to know part of the use case (e.g. the kind of status he needs to filter). It also means that if the business logic ever changes (e.g. another editable status is being introduced, say, partly-active
), the client would need to be changed (to include that value into his query filter).
- Design a client-specific API and filter server-side instead of client-side. To achieve this, three approaches were being suggested: a) Include a technical field into the resource representation that specifies the client, say
forClient
. The client would then filter that property for e.g. forClient='App1'
. b) Include a ‘technical association’, between a parent resource and the actual resource which would lead to the query look something like this: work-package/forApp1/work-tasks
. Work-package
would be an object that has a 1:n relationship to work-task
. c) Develop a new completely new API per client.
Of course I have consulted the API specs (we use OData V2.0, which is specified here), but the specs never talk explicitely about that point. One could argue that 2) is never being talked about and (1) is always being assumed when looking at e.g. the URI or resource conventions.
I myself use JSON:API personally, which seems to be a little more restrictive and could be interpreted to more specifically demand (1).
I’ve also consulted guidelines on how to implement REST, like here and here. I’d also interpret these as to go for (1). But in the end, I might be too biased and trying to read between the lines.
I’d very much welcome any input on this matter. 🙂
Bonus Question: In case (or in cases where) you would go for (1), would that change when there wouldn’t be only one property to filter, but say 3-5 filters would be required to get the subset required by the client?