I'm looking for some direction in regards to the URI design for a RESTful API. I'm going to have several nested linked resources and have currently designed my URI's similar to this post: Hierarchical RESTful URL design
The following example isn't what I'm building but I think illustrates my situation well. (Assume that a show can only belong to one network).
/networks [GET,POST]
/networks/{network_id} [GET,PUT]
/networks/{network_id}/shows [GET,POST]
/networks/{network_id}/shows/{show_id} [GET,PUT]
/networks/{network_id}/shows/{show_id}/episodes [GET,POST]
/networks/{network_id}/shows/{show_id}/episodes/{episode_id} [GET,PUT]
My situation will go two more levels further with associations but all the associations are one to many. I'm considering switching it to something similar to this:
/networks [GET,POST]
/networks/{network_id} [GET,PUT]
/networks/{network_id}/shows [GET,POST]
/shows [GET]
/shows/{id} [GET,PUT]
/shows/{id}/episodes [GET,POST]
/episodes [GET]
/episodes/{id} [GET,PUT]
My questions are:
Is the second example a valid REST design?
Should I consider implementing both paths?
The second example looks fine to me. The URLs are descriptive of the resources and the correct HTTP verbs are being used.
It is perfectly fine to have multiple URLs pointing to the same resource, if that makes sense. But more importantly, make sure the resources contain <link /> elements that connect shows to networks, episodes to shows, etc.
The real question here: does your second example fulfill the URI standard? The URI standard states, that the path contains the hierarchical part and the query contains the non-hierarchical part, but afaik. it does not tell anything about how to design the URI structure in your situation. The REST uniform interface constraints has a HATEOAS section, which means that you should send back links in your situation, which point to the upper and lower level resources. You should annotate these links with metadata, which can be processed by the client, so it will know what a link is about. So in practice the URI structure does not really matter...
GET /shows/123
{
"label": "The actual show",
"_embedded": {
"episodes": [
{
"label": "The first episode of the actual show",
"_embedded": {
"associations": [
//...
]
},
"_links": {
"self": {
"label": "Link to the first episode of the actual show",
"href": "/episodes/12345"
},
"first": {
"href": "/episodes/12345"
},
"duplicate": {
"href": "/networks/3/shows/123/episodes/12345"
},
"up": {
"label": "Link to the actual show",
"href": "/shows/123"
},
"next": {
"label": "Link to the next episode of the actual show"
"href": "/episodes/12346"
},
"previous": null,
"last": {
"href": "/episodes/12350"
}
}
}//,
//...
]
},
"_links": {
"self": {
"label": "Link to the actual show",
"href": "/shows/123"
},
"duplicate": {
"href": "/networks/3/shows/123"
},
"up": {
"label": "Link to the actual network",
"href": "/networks/3"
},
"collection": {
"label": "Link to the network tree",
"href": "/networks"
},
"next": {
"label": "Link to the next show in the actual network",
"href": "/shows/124"
},
"previous": {
"label": "Link to the previous show in the actual network",
"href": "/shows/122"
}
}
}
Now this is just something very beta in HAL+JSON with IANA link relations, but you can use JSON-LD with an RDF vocabulary (e.g. schema.org+hydra) as well. This example is just about the hierarchy (up, first, next, previous, last, collection, item, etc...), but you should add more metadata e.g. which link points to a network, which to a show, and which to an episode, etc... So your clients will know from the metadata what the content is about, and for example they can use the links to navigate automatically. This is how REST works. So the URI structure does not really matters by the client. (You can use compact URIs and URI templates as well if you want to make your response more compact.)
A URI is "any information that can be given a name"
Your question is a domain related question, and can only really be answered by someone who knows about the resources with which you are naming with a URI.
The question that comes to mind while trying to guess about your domain, is does a "show" really depend on a "network"?
What is a network in your domain? and what is the relationship between a show and a network? Is it simply someone who has aired the show? or is it more to do with production information?
I believe your example 2 is a much better fit.
Considering you have one-to-many relationships in following hierarchy:
network --> shows --> episodes
I think the second design does not provide sufficient information to the Server side to process your request. For example if you have following data:
Network id show_id episode_id
1 1 1
1 2 1
1 1 2
The first design which is verbose will provide sufficient information in HTTP request to fetch data: /networks/1/shows/1/episodes/1
The second design on the contrary will have:
/episodes/1
In the second design there is no way for server side to know if you meant row1 or row 2 from your data
To answer your question:
IMHO 2nd design may not be a valid REST design for your example. A
workaround may be to pass query parameters
I think design 1 is self sufficient
UPDATE: Please ignore my answer above
2nd design is a valid REST design for your example
Only having design 2 should also suffice
Additionally:
/networks
/networks/{id}
/shows
/shows/{id}
/episodes
/episodes/{id}
should be sufficient number of REST URLs
or in other words the following URLs would be redundant:
/networks/{network_id} [GET,PUT]
/networks/{network_id}/shows [GET,POST]
/shows/{id}/episodes [GET,POST]
I think we should keep REST API URL as simple as we can.
e.g. https://www.yoursite.com/api/xml/1.0/
Here I'm taking example of XML API for version 1.0. Please remember to use versions of the API for future updates.
You can check the method which is requested by the client.
e.g. tag
<method>getEpisodes</method>
I think the second option is Ok, but if you wanted to validate relationships, I would consider the first option. For example, when you get an episode with a different network, it can mean that the episode was modificated before your request so maybe you need to response with a 422, the same for the others services. With this, you can be sure that the entity you want to work is involving its parent.
PD: Sorry for my English.
Related
I have the following data structure that contains an array of sectionIds. They are stored in the order in which they were completed:
applicationProgress: ["sectionG", "sectionZ", "sectionA"]
I’d like to be able to do something like:
GET /application-progress - expected: sectionG, sectionZ, sectionA
GET /application-progress?filter[first]=true - expected: sectionG
GET /application-progress?filter[current]=true - expected: sectionA
GET /application-progress?filter[previous]=sectionZ - expected: sectionG
I appreciated the above URLs are incorrect, but I’m not sure how to name/structure them to get the expected data e.g. Are the resources here "sectionids"?
I'd like to adhere to the JSON:API specification.
UPDATE
I'm looking to adhere to JSON:API v1.0
In terms of resources I believe I have "Section" and "ProgressEntry". Each ProgressEntry will have a one-to-one relationship with a Section.
I'd like to be able to query within the collection e.g.
Get the first item in the collection:
GET /progress-entries?filter[first]
Returns:
{
"data": {
"type": "progress-entries",
"id": "progressL",
"attributes": {
"sectionId": "sectionG"
},
"relationships": {
"section": {
"links": {
"related": "http://example.com/sections/sectionG"
}
}
}
},
"included": [
{
"links": {
"self": "http://example.com/sections/sectionG"
},
"type": "sections",
"id": "sectionG",
"attributes": {
"id": "sectionG",
"title": "Some title"
}
}
]
}
Get the previous ProgressEntry given a relative ProgressEntry. So in the following example find a ProgressEntry whose sectionId attribute equals "sectionZ" and then get the previous entry (sectionG). I wasn't clear before that the filtering of this is based on the ProgressEntry's attributes:
GET /progress-entries?filter[attributes][sectionId]=sectionZ&filterAction=getPreviousEntry
Returns:
{
"data": {
"type": "progress-entries",
"id": "progressL",
"attributes": {
"sectionId": "sectionG"
},
"relationships": {
"section": {
"links": {
"related": "http://example.com/sections/sectionG"
}
}
}
},
"included": [
{
"links": {
"self": "http://example.com/sections/sectionG"
},
"type": "sections",
"id": "sectionG",
"attributes": {
"id": "sectionG",
"title": "Some title"
}
}
]
}
I started to comment on jelhan's reply though my answer was just to long for a reasonable comment on his objection, hence I include it here as it more or less provides a good introduction into the answer anyways.
A resource is identified by a unique identifier (URI). A URI is in general independent from any representation format else content-type negotiation would be useless. json-api is a media-type that defines the structure and semantics of representations exchanged for a specific resource. A media-type SHOULD NOT force any constraints on the URI structure of a resource as it is independent from it. One can't deduce the media-type to use based on a given URI even if the URI contains something like vnd.api+json as this might just be a Web page talking about json:api. A client may as well request application/hal+json instead of application/vnd.api+json on the same URI and receive the same state information just packaged in a different representation syntax, if the server supports both representation formats.
Profiles, as mentioned by jelhan, are just extension mechanisms to the actual media-type that allow a general media-type to specialize through adding further constraints, conventions or extensions. Such profiles use URIs similar to XML namespaces, and those URIs NEED NOT but SHOULD BE de-referencable to allow access to further documentation. There is no talk about the URI of the actual resource other than given by Web Linking that URIs may hint a client on the media-type to use, which I would not recommend as this requires a client to have certain knowledge about that hint.
As mentioned in my initial comments, URIs shouldn't convey semantics as link relations are there for!
Link-relations
By that, your outlined resource seems to be a collection of some further resources, sections by your domain language. While pagination as defined in json:api does not directly map here perfectly, unless you have so many sections that you want to split these into multiple pages, the same concept can be used using standardized link relations defined by IANA.
Here, at one point a server may provide you a link to the collection resource which may look like this:
{
"links": {
"self": "https://api.acme.org/section-queue",
"collection": "https://api.acme.org/app-progression",
...
},
...
}
Due to the collection link relation standardized by IANA you know that this resource may hold a collection of entries which upon invoking may return a json:api representation such as:
{
"links": {
"self": "https://api.acme.org/app-progression",
"first": "https://api.acme.org/app-progression/sectionG",
"last": "https://api/acme.org/app-progression/sectionA",
"current": "https://api.acme.org/app-progression",
"up": "https://api.acme.org/section-queue",
"https://api/acme.org/rel/section": "https://api.acme.org/app-progression/sectionG",
"https://api/acme.org/rel/section": "https://api.acme.org/app-progression/sectionZ",
"https://api/acme.org/rel/section": "https://api.acme.org/app-progression/sectionA",
...
},
...
}
where you have further links to go up or down the hierarchy or select the first or last section that finished. Note the last 3 sample URIs that leverages the extension relation types mechanism defined by RFC 5988 (Web Linking).
On drilling down the hierarchy further you might find links such as
{
"links": {
"self": "https://api.acme.org/app-progression/sectionZ",
"first": "https://api.acme.org/app-progression/sectionG",
"prev": "https://api.acme.org/app-progression/sectionG",
"next": "https://api.acme.org/app-progression/sectionA",
"last": "https://api.acme.org/app-progression/sectionA",
"current": "https://api.acme.org/app-progression/sectionA",
"up": "https://api.acme.org/app-progression",
...
},
...
}
This example should just showcase how a server is providing you with all the options a client may need to progress through its task. It will simply follow the links it is interested in. Based on the link relation names provided a client can make informed choices on whether the provided link is of interest or not. If it i.e. knows that a resource is a collection it might to traverse through all the elements and processes them one by one (or by multiple threads concurrently).
This approach is quite common on the Internet and allows the server to easily change its URI scheme over time as clients will only act upon the link relation name and only invoke the URI without attempting to deduce any logic from it. This technique is also easily usable for other media-types such as application/hal+json or the like and allows each of the respective resources to be cached and reused by default, which might take away load from your server, depending on the amount of queries it has to deal with.
Note that no word on the actual content of that section was yet said. It might be a complex summary of things typical to sections or it might just be a word. We could classify it and give it a name, as such even a simple word is a valid target for a resource. Further, as Jim Webber mentioned, your resources you expose via HTTP (REST) and your domain model are not identical and usually do not map one-to-one.
Filtering
json:api allows to group parameters together semantically by defining a customized x-www-form-urlencoded parsing. If content-type negotiation is used to agree on json:api as representation format, the likelihood of interoperability issues is rather low, though if such a representation is sent unsolicitedly parsing of such query parameters might fail.
It is important to mention that in a REST architecture clients should only use links provided by the server and not generate one on their own. A client usually is not interested in the URI but in the content of the URI, hence the server needs to know how to act upon the URI.
The outlined suggestions can be used but also URIs of the form
.../application-progress?filter=first
.../application-progress?filter=current
.../application-progress?filter=previous&on=sectionZ
can be used instead. This approach should in addition to that also work on almost all clients without the need to change their url-encoded parsing mechanism. In addition to that he management overhead to return URIs for other media-types generated may be minimized as well. Note that each of the URIs in the example above represent their own resource and a cache will store responses to such resources based on the URI used to retrieve such results. Queries like .../application-progress?filter=next&on=sectionG and .../application-progress?filter=previous&on=sectionA which retrieve basically the same representations are two distinctive resources which will be processed two times by your API as the response of the first query can't be reused as the cache key (URI) is different. According to Fielding caching is one of the few constraints REST has which has to be respected otherwise you are violating it.
How you design such URIs is completely up to you here. The important thing is, how you teach a client when to invoke such URIs and when it should not. Here, again, link-relations can and should be used.
Summary
In summary, which approach you prefer is up to you as well as which URI style you choose. Clients, especially in a REST environment, do not care about the structure of the URI. They operate on link-relations and use the URI just for invoking it to progress on with their task. As such, a server API should help a client by teaching it what it needs to know like in a text-based computer game in the 70/80's as mentioned by Jim Webber. It is helpful to think of the interaction model to design as affordances and state machine as explained by Asbjørn Ulsberg .
While you could apply filtering on grouped parameters provided by json:api such links may only be usable within the `json:api´ representation. If you copy & paste such a link to a browser or to some other channel, it might not be processable by that client. Therefore this would not be my first choice, TBH. Whether or not you design sections to be their own resource or just properties you want to retrieve is your choice here as well. We don't know really what sections are in your domain model, IMO it sounds like a valid resource though that may or may not have further properties.
I came across HATEOAS on my researches and was thinking : doesn't HATEOAS multiplicate HTTP requests ?
Let's take the basic customer and order example.
Let's say you want to retrieve an order, the endpoint would be /orders/2
with the following JSON response :
{
"id": 2,
"total": 50.00,
"links": [{
"rel": "customer",
"href": "http://api.domain.com/customer/1
}]
}
Now what if I also need the customer ? Do I have to make another request to /customer/1 ? Doesn't this overload the HTTP traffic ?
Couldn't I get the couple customer + order with a single endpoint like /customers/1/orders/2 ?
Or just send the customer in the /orders/2 JSON response ?
{
"id": 2,
"total": 50.00,
"customer": {
"id": 1,
"name": "Dylan Gauthier"
}
}
What's the benefit(s) of one solution or another ? When do I need one or the other ?
Thanks ! :-)
If the server only supplies the customer and order separately, then you have to make two requests regardless of whether they are following REST or not.
Nothing about REST or its HATEOAS constraint prevents the server from providing both customer and order in the same resource, exactly as you have suggested:
GET /orders/2
{
"id": 2,
"total": 50.00,
"customer": {
"name": "Dylan Gauthier"
}
}
But the customer in that response has no connection to the identifier /customers/1 — the server could combine the two ideas:
{
"id": 2,
"total": 50.00,
"links": [{
"rel": "customer",
"href": "http://api.domain.com/customer/1
}],
"resources": {
"http://api.domain.com/customer/1": {
"name": "Dylan Gauthier"
}
}
}
or better yet, group the links by their relation to the requested resource:
{
"id": 2,
"total": 50.00,
"links": {
"customer": [{
"href": "http://api.domain.com/customer/1"
}]
},
"resources": {
"http://api.domain.com/customer/1": {
"name": "Dylan Gauthier"
}
}
}
Whilst this would make it a bit more work for the client to print the name of the customer (nothing at all taxing, mind), it allows the client to fetch more information about the customer if they want to!
Just to add to Nicholas' answer:
Embedding related resources
Pros: saves you a trip to the server
Cons: While it saves you a trip the first time and may be a few lines of code, you are giving up on caching: if something changes in a related resource (that you embedded) client cache is no more valid, so the client has to make the request again. Of course, assuming you leverage HTTP caching. Which you should...
If you want to go this route, you are better off using something like GraphQL... but wait!
Going "pure" HATEOS
Pros: resources have independent life-cycles; easier to make each (type of) resource evolve without impacting the others. By fully leveraging the cache, overtime, the overall performance is far better.
Cons: more requests (at first access), this might be a little slower on first access; some more code to manage the HATEOS thing...
I personally tend to use the second approach whenever possible.
The classic web analogy:
If it can help, a classic website is just another api that serves html related resources, the client app being the browser itself. If you have ever done some html/css/js, you might want to approach it the same way:
For the given particular website, given its navigation architecture...etc would you rather inline all/part of the css/js (the related resources) in the html pages (the main resource) or not.
We want to create a screen on multiple clients that shows "5 best selling product", "5 recently added product" and "5 product with great offers". All these would be shown as carousel.
We want to create Restful APIs for these. We have created following APIs:
/api/bestsellingproduct/
/api/recentlyaddedproduct/
/api/greatofferproduct/
Currently, every client i.e. desktop, mobile, android, ios has hard-coded these URIs. I am worried if we tomorrow change these URLs, it would be cumbersome and also REST suggests that "A REST client enters a REST application through a simple fixed URL. (Ref: https://en.wikipedia.org/wiki/HATEOAS)"
Can someone suggest how I can ensure that all clients enter application through simple fixed URL in this case?
In HATEOAS URIs are discoverable (and not documented) so that they can be changed. That is, unless they are the very entry points into your system (Cool URIs, the only ones that can be hard-coded by clients) - and you shouldn't have too many of those if you want the ability to evolve the rest of your system's URI structure in the future. This is in fact one of the most useful features of REST.
For the remaining non-Cool URIs, they can be changed over time, and your API documentation should spell out the fact that they should be discovered at runtime through hypermedia traversal.
Looking at the Richardson's Maturity Model (level 3), this would be where links come into play. For example, from the top level, say /api/version(/1), you would discover there's a link to the groups. Here's how this could look in a tool like HAL Browser:
Root:
{
"_links": {
"self": {
"href": "/api/root"
},
"api:bestsellingproduct": {
"href": "http://apiname:port/api/bestsellingproduct"
},
"api:recentlyaddedproduct": {
"href": "http://apiname:port/api/recentlyaddedproduct"
},
"api:greatofferproduct": {
"href": "http://apiname:port/api/greatofferproduct")
}
}
}
The advantage here would be that the client would only need to know the relationship (link) name (well obviously besides the resource structure/properties), while the server would be mostly free to alter the relationship (and resource) url.
You could even embed them to be returned in the same root api call:
{
"_embedded": {
"bestsellingproduct": [
{
"id": "1",
"name": "prod test"
},
{
"id": "2",
"name": "prod test 2"
}
],
"recentlyaddedproduct": [
{
"id": "3",
"name": "prod test 3"
},
{
"id": "5",
"name": "prod test 5"
}
]
}
I understand HATEOAS represents the applications state by sending all actions that can be performed at that point in time within the application as it's response (HAL, JSON-LD, etc).
For example, viewing an account resource of a bank may allow you to deposit, withdraw or close the account (OPTIONS which may return UPDATE and DELETE verbs).
In terms of runtime discoverability of these links (by the consuming client), how might one go about this?
If the purpose of sending these links is the decouple the client from the server and drive the state by the hypermedia in the response, there must be an amount of knowledge the developer must hardcode in the application in order to make any sense of the responses being returned.
I understanding sending OPTIONS requests is the way to determine the current state of the resource and what you can do next, but in order to discover the actual URIs to use - would these simply be hardcoded as COOL URIs?
Like #VoicesOfUnreason said, in HATEOAS URIs are discoverable (and not documented) so that they can be changed. That is, unless they are the very entry points into your system (Cool URIs, the only ones that can be hard-coded by clients) - and you shouldn't have too many of those if you want the ability to evolve the rest of your system's URI structure in the future. This is in fact one of the most useful features of REST.
For the remaining non-Cool URIs, they can be changed over time, and your API documentation should spell out the fact that they should be discovered at runtime through hypermedia traversal.
Looking at the Richardson's Maturity Model (level 3), this would be where links come into play. For example, from the top level, say /api/version(/1), you would discover there's a link to the groups. Here's how this could look in a tool like HAL Browser:
Root:
{
"_links": {
"self": {
"href": "/api/root"
},
"api:group-add": {
"href": "http://apiname:port/api/group"
},
"api:group-search": {
"href": "http://apiname:port/api/group?pageNumber={pageNumber}&pageSize={pageSize}&sort={sort}"
},
"api:group-by-id": {
"href": "http://apiname:port/api/group/id" (OR "href": "http://apiname:port/api/group?id={id}")
}
}
}
The add would simply be a POST to that endpoint, and then you'd have 2 GET methods.
GET /api/group?pageNumber=0&pageSize=20&sort=asc
which could return something like this:
{
"groups": [
{
"id": 123,
"name": "Test Group"
},
{
"id": 134,
"name": "Tennis squad"
}
]
}
Then once you drill down to a particular group (say #123):
{
"Id" : 123,
"Name" : "test",
"_links": {
"self": {
"href": "/api/group/1" (OR "/api/group?id=1")
},
"edit": {
"href": "http://apiname:port/api/group/1"
},
"api:delete": {
"href": "http://apiname:port/api/group/1"
},
"api:items-query": {
"href": "http://apiname:port/api/bonus?groupId=1"
}
}
}
Here, the edit would simply be a PUT, and then you'll need a DELETE (see level 2 of REST in that same link), as for the items, you probably know best if they are just a property, or another endpoint; you could even embed them to be returned in the same call that's retrieving a group.
The advantage here would be that the client would only need to know the relationship (link) name (well obviously besides the resource structure/properties), while the server would be mostly free to alter the relationship (and resource) url.
There's a bunch of prior art around on trying to create expressive, discoverable hypermedia. You might want to review:
http://json-ld.org/
http://www.markus-lanthaler.com/hydra/
I am thinking maybe a series of if statement that checks for certain properties to determine the state or maybe even switch statements. Is this is correct path - or is there better means of hypermedia discovery?
My current thinking is that you want to be shaping your ideas more along the lines of negotiating and following a protocol; so think state machine rather than if statements.
For starters, review How To GET a Cup of Coffee.
The hyperlinks in the documents served by RESTBucks are designed to assist the client in negotiating the RESTBucks protocol; the assumption that the client already understands that protocol is baked into the model. In other words, the client already understands that negotiating the protocol will allow it to reach it's goal.
Of course, there could be multiple protocols that serve the same goal. For instance RESTBucks could also support a "Give Away Day Old Coffee" protocol; announcing the presence of each, the client would be expected to choose which is the better expression of the goal, and follow that path.
If I wanted to create (POST) a new resource linking two independent resources, what is the most proper - with respect to HATEOAS and REST principles - way to structure the entity of the request?
Any references in RFCs, W3C documents, Fielding's thesis, etc., about the proper way for a client to request two independent resources be linked together would be most valuable. Or, if what I'm interested in is simply outside the scope of REST, HATEOAS, an explanation of why would also be great.
Hopefully my question above is clear. If not, here's a scenario and some background to ground the question.
Let's say I have two independent resources: /customer and /item, and a third resource /order intended to the two.
If I'm representing these resource to the client in a HATEOAS-like way (say with JSON-LD), a customer might (minimally) look like:
{
"#id": "http://api.example.com/customer/1"
}
and similarly an item like:
{
"#id": "http://api.example.com/item/1"
}
I'm more concerned about what scheme the entity of the POST request should have, rather than the URL I'm addressing the request to. Assuming I'm addressing the request to /order, would POSTing the following run afoul of HATEOAS and REST principles in any way?
{
"customer": {"#id": "http://api.example.com/customer/1"},
"item": {"#id": "http://api.example.com/item/1"}
}
To me, this seems intuitively OK. However, I can't find much or any discussion of the right way to link two independent resources with a POST. I discovered the LINK and UNLINK HTTP methods, but these seem inappropriate for a public API.
The client does not build URIs, so this is wrong unless these resource identifiers or at least their template came from the service. It is okay to use the id numbers instead of the URIs until you describe this in the response which contains the POST link.
An example from the hydra documentation:
{
"#context": "http://www.w3.org/ns/hydra/context.jsonld",
"#id": "http://api.example.com/doc/#comments",
"#type": "Link",
"title": "Comments",
"description": "A link to comments with an operation to create a new comment.",
"supportedOperation": [
{
"#type": "CreateResourceOperation",
"title": "Creates a new comment",
"method": "POST",
"expects": "http://api.example.com/doc/#Comment",
"returns": "http://api.example.com/doc/#Comment",
"possibleStatus": [
... Statuses that should be expected and handled properly ...
]
}
]
}
The "http://api.example.com/doc/#Comment" contains the property descriptions.
{
"#context": "http://www.w3.org/ns/hydra/context.jsonld",
"#id": "http://api.example.com/doc/#Comment",
"#type": "Class",
"title": "The name of the class",
"description": "A short description of the class.",
"supportedProperty": [
... Properties known to be supported by the class ...
{
"#type": "SupportedProperty",
"property": "#property", // The property
"required": true, // Is the property required in a request to be valid?
"readable": false, // Can the client retrieve the property's value?
"writeable": true // Can the client change the property's value?
}
]
}
A supported property can have an rdfs:range, which describes the value constraints. This is not yet (2015.10.22.) added to the hydra vocab as far as I can tell, but I don't have time to follow the project. I think you still can use the rdfs:range instead of waiting for a hydra range.
So in your case you could add an item property with a range of http://api.example.com/doc/#Item and so on. I assume you could add the links of the alternatives, something like http://api.example.com/items/, so you could generate a select input box. Be aware that this technology is not stable yet.
So you can send a simple JSON as POST body {item: {id:1}, customer: {id:1}} or something like that, which you generate based on the POST link. The RDF is for the client not for the server. The server can understand the data structure it requires, it does not need RDF. You don't need a dictionary to understand yourself...