I'm developing my first RESTful api, which (unfortunately) is being done on an already existing system and the idea is to allow third-parties to access this system.
Everything was fine until I realised that I have multiple ways to access the same resources. I will try to explain it using one of the parts of the system. The system has been built using Laravel 5.8 and has, among others, the following database tables:
Each user can have many emails, and each email belongs to only one user. The same applies for text messages.
I've "ignored" all the current code, because it wasn't built on a proper way to make it an RESTful api, so I've created a new folder Api
and all my code is there.
I thought it would make sense to have the following endpoints
/api/v1/users
/api/v1/users/1
/api/v1/users/1/emails
/api/v1/users/1/emails/1
/api/v1/users/1/sms
/api/v1/users/1/sms/1
In this way I can have a list of users, get all the details of a user, get a list of emails/text messages and also get all the details of a specific email/text message. However, one of the requirements is to have a page with a list of emails/text messages, so it's starting to make sense to have:
/api/v1/emails
/api/v1/emails/1
/api/v1/sms
/api/v1/sms/1
To avoid having 2 endpoints to get the same resource (/api/v1/users/1/emails/1
and /api/v1/emails/1
will return the email with id 1) I'm considering to get rid of the deep endpoints /api/v1/users/1/emails
and change them to something like /api/v1/emails?user_id=1
.
Is this against RESTful principles? I couldn't reach a conclusion on my research about having 2 endpoints to access the same resource, but it doesn't "feel" right. On the other hand, having /api/v1/emails?user_id=1
may rise some security/privacy concerns (for example, I need to make sure that user 1 can only access /api/v1/emails?user_id=1
and not /api/v1/emails?user_id=2
), but seems more flexible because I can use it alone to get all the resources or with the user_id filter to get only specific resources.
Is there a convention for this case?
It may help to review how we understand "resources" in a REST context.
Any information that can be named can be a resource: a document or image, a temporal service (e.g. "today's weather in Los Angeles"), a collection of other resources, a non-virtual object (e.g. a person), and so on. In other words, any concept that might be the target of an author's hypertext reference must fit within the definition of a resource.
/api/v1/users/1/emails
/api/v1/emails?user_id=1
/66eb6757-254e-49b4-bc8a-d04330f4482e
REST treats identifiers as semantically opaque -- general purpose clients do not use the spelling of the identifier to understand what is going on. Consider a web browser - it knows that http://example.org/cat.jpg
is an image not because jpg
, but because img
.
That means that the server may use any spelling it likes -- any information encoded into the URI itself is done at the server's discretion and for its own use.
This isn't to say that there aren't advantages to using "guessable" spellings; just that REST is completely agnostic about whether or not identifiers should be guessable.
Choosing spellings for your identifiers that make your implementation simpler is completely within bounds.
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