Reputation: 129
I'm working through a transition of my app from a tightly coupled PHP implementation to a RESTful implementation. (current app at http://coinvault.tanichols.com)
The app maintains a collection of coins (state quarters, presidential dollars, etc) and users. A user can also 'collect' a coin, represented as a many-many relationship between the user and coin tables.
I've created the following table of verb and endpoint combinations:
GET /coins - Get all coins
POST /coins - Create a new coin
GET /coins/CID - Get a coin
PUT /coins/CID - Update a coin
DELETE /coins/CID - Delete a coin
GET /users - Get all users
POST /users - Create a new user
GET /users/UID - Get a user
PUT /users/UID - Update a user
DELETE /users/UID - Delete a user
What I'm having trouble with is the proper/accepted way of exposing information from the many-many table. For example, I could use the following set of routes:
GET /users/UID/coins - Get coins for a user
POST /users/UID/coins - Create a coin for a user
GET /users/UID/coins/CID - Get a specific coin for a user
PUT /users/UID/coins/CID - Update a specific coin for a user
DELETE /users/UID/coins/CID - Delete a specific coin for a user
or I could invert this to:
GET /coins/CID/users/UID - Get a specific coin for a user
PUT /coins/CID/users/UID - Update a specific coin for a user
DELETE /coins/CID/users/UID - Delete a specific coin for a user
Q1: Is one of these preferred over the other? Is there a standard or accepted way of planning these types of routes?
I could also expose this functionality with the following route and filter:
GET /coins?user_id=1 - Get all coins belonging to a user
Q2: Is this a better approach, or worse? Does this add unnecessary 'weight' to the /coins route?
Finally, there's the situation where I want to provide access to some aggregations, such as a count of how many times a particular coin has been collected, for reporting and analytics purposes. For this one, I'm at a complete loss on where to begin, or how to approach the problem.
Q3: How does one expose such aggregations through a RESTful API? What is a meaningful route for this?
Upvotes: 3
Views: 2026
Reputation: 5291
Q1:
The way you represent collections and items is valid in absolute but your first proposal is valid in your context:
GET /users/UID/coins - Get coins for a user
POST /users/UID/coins - Create a coin for a user
GET /users/UID/coins/CID - Get a specific coin for a user
PUT /users/UID/coins/CID - Update a specific coin for a user
DELETE /users/UID/coins/CID - Delete a specific coin for a user
If a thing belongs to someone, you represent it with /someones/SID/things/TID.
Q2:
This proposal:
GET /coins?user_id=1 - Get all coins belonging to a user
is definitely not a good idea, it goes against REST best practices.
Q3:
It's not a matter of aggregation, these data are bound to a coin, therefore you could simply return them within the data of GET /coins/CID
.
Multiplying endpoints is definitely not a good idea, especially if these data will be always needed.
Upvotes: 3