In my project I have a Team entity. Its structure looks like that:
id: long; // primary key
teamNumber: string; // unique team number, numeric, but can contain leading zeroes
title: string; // team title
I have a REST-endpoint to get team by id, and the address of this endpoint name pattern looks like that:
/teams/{id}
So, if I want to get a team by its id, for example for id=123, I make the GET-request to:
/teams/123
But, also it is required to have an endpoint to get a team by team number (not id).
And in this case I can't have a REST-endpoint with the same pattern:
/teams/{teamNumber}
Because it conflicts with the
/teams/{id}
I should have another unique address for this (get) request.
My question: what is the best practice to name REST-endpoint addresses for such cases?
Should I have something like:
/teams/team-by-number/{teamNumber}
Or there is a better approach?
If you have 2 unique ways to find these resources, and both can potentially collide (they're both numbers), then yes you will definitely need 2 different namespaces.
Your approach to this is fine.
I would question if you can't just use one of the two, because I can imagine that having 2 unique numeric identifiers can easily confuse people. If this is a hard requirement, then I think you're on the right path.
Well, what you are using is called path parameter. You can also use query parameters. Something like below:
/teams?id=123 or /teams?teamNumber=123
This is just another way. It's up to you.
In this conflicting case, according to the conventions, I'd recommend:
/teams/id/{id}
/teams/team-number/{teamNumber}
Related
Basing on the naming conventions found here : https://restfulapi.net/resource-naming/ , I have a particular question to which I can not find an answer.
Taking the example of customers and accounts where sub-collection resource “accounts” of a particular “customer” can be identified using the URN “/customers/{customerId}/accounts” , how do I find accounts for multiple customer IDs? What are the naming conventions for such a case?
Is the only option to use filters? eg: customers/accounts?customerId=12,22
I tend to avoid filters and keep everything as a urn and keep the implementation of the backend system hidden. e.g. this
customers/accounts?customerId=12,22
means the client needs to know that customers are represented in the system by a variable called customerId. Clients shouldn't need to know that. They just need to know that customers have numbers, IMHO anyway.
This answer shows a solution for your situation, which would look like:
customers/accounts/12,22
although to keep it in line with the domain, where customers have ids and associated accounts, it would look like:
customers/12,22/accounts
and your backend framework would give you the list of customer 'numbers' from the url and at that point they become customerIds.
Not all frameworks may support arrays in paths but pick the right tool for the job and you can design your API to be elegant and a good match for your domain.
I have a REST syntaxe question:
what url do you give to an endpoint to extract data similar to the record which from the id passed?
By exemple : I have a class Record:
Record {id:12, phoneNumber:"+336746563"}
I want a endpoint who will return all the records who share the same phoneNumber than the record with the id 12
which url respect the most the REST protocol ?
EDIT IMPORTANT : the client DON't know the phone number when he call the url. only the 12 id.
what url do you give to an endpoint to extract data similar to the record which from the id passed?
Anything you want -- the machines don't care what spelling you use for your resource identifiers.
I want a endpoint who will return all the records who share the same phoneNumber than the record with the id 12
/all-records-with-same-phone-number-as?id=12
/all-records-with-same-phone-number-as?12
/all-records-with-same-phone-number-as/12
All of these examples are fine. They have different trade offs -- the first one is really easy to generate using an HTML form. The last once allows you do interesting things with relative references and dot-segments.
/record/12/all-records-with-same-phone-number
similar to the above, we've just juggled the order of the path segments a little bit. Might be useful if we want to have relative references to other resources under the same /record/12 stem.
If you are expecting to need to paginate, then you might want to think about how the paging parameters fit with everything else. Again, the machines don't care, but some spellings are easier to work with than others.
I am not sure if I understand the question but let me try.
You can do this in various ways which is best suited for you w.r.t. your programming language. For example, domain.com/api/records/123456 can be the end-point. 123456 is a parameter and your code will return all the records having phoneNumber=123456.
Alternatively, the end-point can be domain.com/api/records?phoneNumber=12345.
Or Even, domain.com/api/records/123456/phonenumber.
The other option is to have the request data in the body and the domain would just look like domain.com/api/records with request as {"PhoneNumber":"123456"}
AFAIK, all these URLs respect REST protocol.
I would use something like
/service/records/{id}/similar
where the service would define similarity. It depends on the usecases for when Record becomes more complex and the client should able to specify fields.
This would sooner or later result in queries that would not be based on an existing record and my look like
/service/records?foo=1&bar=2
I could also think of
/service/records/phone-number/12345
because you are really interested in records with the same phoneNumber, not similarity?
But again, as things get more complex you will be better off with a query I think.
Let's take the following resource in my REST API:
GET `http://api/v1/user/users/{id}`
In normal circumstances I would use this like so:
GET `http://api/v1/user/users/aabc`
Where aabc is the user id.
There are times, however, when I have had to design my REST API in a way that some extra information is passed with the ID. For example:
GET `http://api/v1/user/users/customer:1`
Where customer:1 denotes I am using an id from the customer domain to lookup the user and that id is 1.
I now have a scenario where the identifier is more than one key (a composite key). For example:
GET `http://api/v1/user/users/customer:1;type:agent`
My question: in the above URL, what should I use as the separator between customer:1 and type:agent?
According to https://www.ietf.org/rfc/rfc3986.txt I believe that the semi-colon is not allowed.
You should either:
Use parameters:
GET http://api/v1/user/users?customer=1
Or use a new URL:
GET http://api/v1/user/users/customer/1
But use Standards like this
("Paths tend to be cached, parameters tend to not be, as a general rule.")
Instead of trying to create a general structure for accessing records via multiple keys at once, I would suggest trying to think of this on more of a case-by-case basis.
To take your example, one way to interpret it is that you have multiple customers, and those customers each may have multiple user accounts. A natural hierarchy for this would be:
/customer/x/user/y
Often an elegant decision like this can be made, that not only solves the problem but also documents your data-model in a way that someone can easily see that users belong to customers via a 1-to-many relationship.
I am developing a generic REST API for my projects and I'm wondering what to do when I have a table/resource with 2 or more primary keys.
For example, lets suppose I have a table named "question" with two primary keys (date and type) and I need to create the resource REST URI. What is the best way to do it following the standard schema api/{resource}/{id}?
Maybe something like: api/question/{:date},{:type}? What is the best way to do it?
Thank you.
I think that what you call multiple primary keys is a composite key. Right?
You have some options.
Use api/questions/dates/:date/types/:type
Maybe, the best alternative for you is:
api/questions/dates/{:date}/types/{:type}
This is more natural to read as a http resource for your case, even if don't make sense have a api/question/dates/{:date} in your application.
Use api/questions/:date/:type/
Another alternative is:
api/questions/:date/:type/
Use query parameter
If it's no a problem for you, instead of return a single object question you can return an array of questions as response using a filter query, like:
api/questions?date=2022-10-27&type=XYZ
Both are not mandatory, but if the user send both, the return will be always an array with a single element. Also this bring some flexibility to your API, because the user can inform just one of them and have some results. You need to check if this behavior it's valid for your case.
You're on the right path, I think you definitely should include both the date and the type in the resource url if that's the only way you can uniquely identify it
api/question/{date}_{type}
This is a good example of when to use a slug. This answer to What is a slug provides a good idea of how you can use your composite primary key in your api design.
with that, you have a few options at your disposal. Which is the best would be a matter of opinion and what suits your needs.
api/question/{:date}/{:type} or api/question/{:key1}/{:key2}/.../{:keyn}
The same pattern could also be applied to the following.
api/question/{:date}_{:type}
api/question/{:date}-{:type}
I do not find it a good idea of having two primary keys for a resource. REST heavily depends on resources and it's representations.
If you are struck into situation where you are ending up with two identifiers for a resource - then redesign your application (may be by creating another key in backend after mapping it to other identifiers) and add these multiple keys as attributes in resource.
Idea is - "keep it simple" if you want to create truly world class REST APIs.
Bonus: You don't need to teach few extra things to clients/developers about something fancy you did with your APIs.
Simple question I'm having trouble finding an answer to..
If I have a REST web service, and my design is not using url parameters, how can I specify two different keys to return the same resource by?
Example
I want (and have already implemented)
/Person/{ID}
which returns a person as expected.
Now I also want
/Person/{Name}
which returns a person by name.
Is this the correct RESTful format? Or is it something like:
/Person/Name/{Name}
You should only use one URI to refer to a single resource. Having multiple URIs will only cause confusion. In your example, confusion would arise due to two people having the same name. Which person resource are they referring to then?
That said, you can have multiple URIs refer to a single resource, but for anything other than the "true" URI you should simply redirect the client to the right place using a status code of 301 - Moved Permanently.
Personally, I would never implement a multi-ID scheme or redirection to support it. Pick a single identification scheme and stick with it. The users of your API will thank you.
What you really need to build is a query API, so focus on how you would implement something like a /personFinder resource which could take a name as a parameter and return potentially multiple matching /person/{ID} URIs in the response.
I guess technically you could have both URI's point to the same resource (perhaps with one of them as the canonical resource) but I think you wouldn't want to do this from an implementation perspective. What if there is an overlap between IDs and names?
It sure does seem like a good place to use query parameters, but if you insist on not doing so, perhaps you could do
person/{ID}
and
personByName/{Name}
I generally agree with this answer that for clarity and consistency it'd be best to avoid multiple ids pointing to the same entity.
Sometimes however, such a situation arises naturally. An example I work with is Polish companies, which can be identified by their tax id ('NIP' number) or by their national business registry id ('KRS' number).
In such case, I think one should first add the secondary id as a criterion to the search endpoint. Thus users will be able to "translate" between secondary id and primary id.
However, if users still keep insisting on being able to retrieve an entity directly by the secondary id (as we experienced), one other possibility is to provide a "secret" URL, not described in the documentation, performing such an operation. This can be given to users who made the effort to ask for it, and the potential ambiguity and confusion is then on them, if they decide to use it, not on everyone reading the documentation.
In terms of ambiguity and confusion for the API maintainer, I think this can be kept reasonably minimal with a helper function to immediately detect and translate the secondary id to primary id at the beginning of each relevant API endpoint.
It obviously matters much less than normal what scheme is chosen for the secret URL.