Let's say you are creating a REST API for a system that requires approval, e.g. a group membership system (closest analogy I can think of).
My resource for membership is /membership
. I can see 3 possibilities:
A. Single resource.
So a new request is POST /api/membership
which creates {group: 10, user:1, status:"pending"}
. The org admin then approves by PATCH /api/membership/:membership {status: "member"}
Pro: single API. Con: Harder to easily differentiate between different member types; after all, a "pending" member isn't really a member. More importantly, a request to join isn't actually a membership.
B. Separate resources.
A new request is POST /api/join
which creates a request to join {group: 10, user: 1, status:"pending"}
. The org admin then approves by PATCH /api/join/:join {status: "approved"}
. This then automatically (on the server) creates another resources at /api/membership/:membership
.
Pro: Cleanly separates requests to join from actual memberships. Con: Seems redundant (the properties of a request and a membership are similar), and depends on automatically juggling one resource from another on the back-end.
C. Separate resources and requests.
Just like Option B, except that the org admin approves in 2 steps. First POST /api/membership {group:10, user:1}
and then PATCH /api/join/:join {status:"approved"}
.
Pro: Cleanly separates requests from actual memberships. Also does not rely on background processing of one resource to affect another. Con: Relying on the UI to do it is even messier!
Help?
I would handle this as two separate resources. A membership request and a membership are two different things. In addition, they may happen to have very similar properties now, but if they diverge in the future you'll be stuck. I would do
POST /membership-requests
{
"memberId": 7,
"groupId": 15
}
to create the request. The admin could do
GET /membership-requests?groupId=15&status=pending
to get requests by group, and then
PUT /membership-requests/12345
{
"status": "approved"
}
to approve the request. You could use server-side business logic to detect the status change and create the membership. That PUT could then return a link to the membership:
{
"memberId": 7,
"groupId": 15,
"status": "approved",
"membership": "/memberships/298"
}
If you do this, your business logic needs to make sure that only pending requests can have their status changed.
If you only use one resource, how will you handle rejected memberships? To me, it doesn't make sense to do a
GET /memberships?status=rejected
because if the request is rejected, that's not really a membership.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With