From 15ae3a64b32efdfb1624a58ebff822c9d0525520 Mon Sep 17 00:00:00 2001 From: alien-mcl Date: Sat, 5 Jun 2021 21:29:07 +0200 Subject: [PATCH 1/9] Added support for strongly typed collections --- spec/latest/core/core.jsonld | 2 +- spec/latest/core/index.html | 25 ++++++++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/spec/latest/core/core.jsonld b/spec/latest/core/core.jsonld index 8206777..b888324 100644 --- a/spec/latest/core/core.jsonld +++ b/spec/latest/core/core.jsonld @@ -388,7 +388,7 @@ "@id": "hydra:memberAssertion", "label": "member assertion", "comment": "Semantics of each member provided by the collection.", - "domain": "hydra:Collection", + "domainIncludes": ["hydra:Collection", "hydra:Class"], "isDefinedBy": "http://www.w3.org/ns/hydra/core", "vs:term_status": "testing" }, diff --git a/spec/latest/core/index.html b/spec/latest/core/index.html index af3b75a..4244f4e 100644 --- a/spec/latest/core/index.html +++ b/spec/latest/core/index.html @@ -1032,7 +1032,7 @@

Member assertions

+         title="Member assertion block describes relation with another resource">
       
+    
From 8e1feb49b9b480cf2e38505c10aa73410d81652b Mon Sep 17 00:00:00 2001 From: alien-mcl Date: Sat, 10 Jul 2021 21:27:47 +0200 Subject: [PATCH 2/9] Added two more paragraphs as pointed in the review --- spec/latest/core/index.html | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/spec/latest/core/index.html b/spec/latest/core/index.html index cbbfe2d..2c035da 100644 --- a/spec/latest/core/index.html +++ b/spec/latest/core/index.html @@ -1032,7 +1032,7 @@

Member assertions

+         title="Member assertion describes relation with another resource">
       
     
+ +

It is worth to mention that a strongly typed collection instance can have its own + member assertions. n such scenario, both API documentation level and instance + level assertions should be combined neither makes the other obsolete.

+ +

More complex scenario would involve a class hierarchy, in which each class can + carry additional member assertions compared to it's base class. To discover all + available member assertion blocks client SHOULD traverse whole class hierarchy + to gather all of the member assertions. In order to take such a burden from clients + it is strongly recommended to provide all member assertion blocks to be provided + on each class level including it's base class blocks so the client does not have + to perform this traversing behavior.

From 14eeb030fd8c635f57d3da5d517089d914110de5 Mon Sep 17 00:00:00 2001 From: alien-mcl Date: Sat, 18 Sep 2021 14:23:08 +0200 Subject: [PATCH 3/9] Minor typo fixes --- spec/latest/core/index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/latest/core/index.html b/spec/latest/core/index.html index 2c035da..9e9039a 100644 --- a/spec/latest/core/index.html +++ b/spec/latest/core/index.html @@ -1099,8 +1099,8 @@

Member assertions

It is worth to mention that a strongly typed collection instance can have its own - member assertions. n such scenario, both API documentation level and instance - level assertions should be combined neither makes the other obsolete.

+ member assertions. In such scenario, both API documentation level and instance + level assertions should be combined as neither makes the other obsolete.

More complex scenario would involve a class hierarchy, in which each class can carry additional member assertions compared to it's base class. To discover all From c836e6757496d7d8d3440d5303d1d21aefc6c94b Mon Sep 17 00:00:00 2001 From: alien-mcl Date: Mon, 6 Dec 2021 18:56:03 +0100 Subject: [PATCH 4/9] Prepared a draft version of a possible release candidate of the specification. --- spec/latest/core/core.jsonld | 41 +- spec/latest/core/index.bs | 5982 +++++++++++++++++++++++++++ spec/latest/core/index.html | 6851 +++++++++++++++++++++++-------- spec/latest/core/vocabulary.png | Bin 22555 -> 122000 bytes 4 files changed, 11213 insertions(+), 1661 deletions(-) create mode 100644 spec/latest/core/index.bs diff --git a/spec/latest/core/core.jsonld b/spec/latest/core/core.jsonld index b95befe..1331821 100644 --- a/spec/latest/core/core.jsonld +++ b/spec/latest/core/core.jsonld @@ -92,7 +92,7 @@ "@id": "http://www.w3.org/ns/hydra/core", "@type": "owl:Ontology", "label": "The Hydra Core Vocabulary", - "comment": "A lightweight vocabulary for hypermedia-driven Web APIs", + "comment": "A lightweight vocabulary for hypermedia-driven Web APIs.", "seeAlso": "https://www.hydra-cg.com/spec/latest/core/", "preferredPrefix": "hydra", "dc:description": "The Hydra Core Vocabulary is a lightweight vocabulary to create hypermedia-driven Web APIs. By specifying a number of concepts commonly used in Web APIs it enables the creation of generic API clients.", @@ -132,7 +132,7 @@ "@id": "hydra:apiDocumentation", "@type": "hydra:Link", "label": "apiDocumentation", - "comment": "A link to the API documentation", + "comment": "A link to the API documentation.", "range": "hydra:ApiDocumentation", "domain": "hydra:Resource", "isDefinedBy": "http://www.w3.org/ns/hydra/core", @@ -143,7 +143,7 @@ "@type": "hydra:Class", "subClassOf": "hydra:Resource", "label": "ApiDocumentation", - "comment": "The Hydra API documentation class", + "comment": "The Hydra API documentation class.", "isDefinedBy": "http://www.w3.org/ns/hydra/core", "vs:term_status": "testing" }, @@ -151,7 +151,7 @@ "@id": "hydra:entrypoint", "@type": "hydra:Link", "label": "entrypoint", - "comment": "A link to main entry point of the Web API", + "comment": "A link to main entry point of the Web API.", "domain": "hydra:ApiDocumentation", "range": "hydra:Resource", "isDefinedBy": "http://www.w3.org/ns/hydra/core", @@ -161,7 +161,7 @@ "@id": "hydra:supportedClass", "@type": "hydra:Link", "label": "supported classes", - "comment": "A class known to be supported by the Web API", + "comment": "A class known to be supported by the Web API.", "domain": "hydra:ApiDocumentation", "range": "rdfs:Class", "isDefinedBy": "http://www.w3.org/ns/hydra/core", @@ -171,7 +171,7 @@ "@id": "hydra:possibleStatus", "@type": "hydra:Link", "label": "possible status", - "comment": "A status that might be returned by the Web API (other statuses should be expected and properly handled as well)", + "comment": "A status that might be returned by the Web API (other statuses should be expected and properly handled as well).", "range": "hydra:Status", "domainIncludes": ["hydra:ApiDocumentation", "hydra:Operation"], "isDefinedBy": "http://www.w3.org/ns/hydra/core", @@ -181,7 +181,7 @@ "@id": "hydra:supportedProperty", "@type": "hydra:Link", "label": "supported properties", - "comment": "The properties known to be supported by a Hydra class", + "comment": "The properties known to be supported by a Hydra class.", "domain": "rdfs:Class", "range": "hydra:SupportedProperty", "isDefinedBy": "http://www.w3.org/ns/hydra/core", @@ -199,7 +199,7 @@ "@id": "hydra:property", "@type": "rdf:Property", "label": "property", - "comment": "A property", + "comment": "A property.", "range": "rdf:Property", "domainIncludes": ["hydra:SupportedProperty", "hydra:IriTemplateMapping"], "isDefinedBy": "http://www.w3.org/ns/hydra/core", @@ -247,7 +247,7 @@ "@id": "hydra:supportedOperation", "@type": "hydra:Link", "label": "supported operation", - "comment": "An operation supported by instances of the specific Hydra class, or the target of the Hydra link, or IRI template.", + "comment": "An operation supported by instances of the specific Hydra class, or the target of the Hydra link, or Iri template.", "range": "hydra:Operation", "domainIncludes": ["rdfs:Class", "hydra:Class", "hydra:Link", "hydra:TemplatedLink", "hydra:SupportedProperty"], "isDefinedBy": "http://www.w3.org/ns/hydra/core", @@ -257,7 +257,7 @@ "@id": "hydra:operation", "@type": "hydra:Link", "label": "operation", - "comment": "An operation supported by the Hydra resource", + "comment": "An operation supported by the Hydra resource.", "domain": "hydra:Resource", "range": "hydra:Operation", "isDefinedBy": "http://www.w3.org/ns/hydra/core", @@ -275,7 +275,7 @@ "@id": "hydra:method", "@type": "rdf:Property", "label": "method", - "comment": "The HTTP method.", + "comment": "The protocol method.", "domain": "hydra:Operation", "range": "xsd:string", "isDefinedBy": "http://www.w3.org/ns/hydra/core", @@ -295,7 +295,7 @@ "@id": "hydra:returns", "@type": "hydra:Link", "label": "returns", - "comment": "The information returned by the Web API on success", + "comment": "The information returned by the Web API on success.", "domain": "hydra:Operation", "rangeIncludes": ["rdfs:Resource", "hydra:Resource", "rdfs:Class", "hydra:Class"], "isDefinedBy": "http://www.w3.org/ns/hydra/core", @@ -313,7 +313,7 @@ "@id": "hydra:statusCode", "@type": "rdf:Property", "label": "status code", - "comment": "The HTTP status code. Please note it may happen this value will be different to actual status code received.", + "comment": "The response status code. Please note it may happen this value will be different to actual status code received.", "domain": "hydra:Status", "range": "xsd:integer", "isDefinedBy": "http://www.w3.org/ns/hydra/core", @@ -418,7 +418,7 @@ "@id": "hydra:member", "@type": "hydra:Link", "label": "member", - "comment": "A member of the collection", + "comment": "A member of the collection.", "domain": "hydra:Collection", "isDefinedBy": "http://www.w3.org/ns/hydra/core", "vs:term_status": "testing" @@ -436,7 +436,7 @@ "@type": "hydra:Class", "subClassOf": "hydra:Resource", "label": "PartialCollectionView", - "comment": "A PartialCollectionView describes a partial view of a Collection. Multiple PartialCollectionViews can be connected with the the next/previous properties to allow a client to retrieve all members of the collection.", + "comment": "A PartialCollectionView describes a partial view of a Collection. Multiple PartialCollectionViews can be connected with the next/previous properties to allow a client to retrieve all members of the collection.", "isDefinedBy": "http://www.w3.org/ns/hydra/core", "vs:term_status": "testing" }, @@ -494,7 +494,7 @@ "@id": "hydra:search", "@type": "hydra:TemplatedLink", "label": "search", - "comment": "A IRI template that can be used to query a collection.", + "comment": "A Iri template that can be used to query a collection.", "range": "hydra:IriTemplate", "domain": "hydra:Resource", "isDefinedBy": "http://www.w3.org/ns/hydra/core", @@ -552,7 +552,7 @@ "@id": "hydra:variableRepresentation", "@type": "rdf:Property", "label": "variable representation", - "comment": "The representation format to use when expanding the IRI template.", + "comment": "The representation format to use when expanding the Iri template.", "range": "hydra:VariableRepresentation", "domain": "hydra:IriTemplateMapping", "isDefinedBy": "http://www.w3.org/ns/hydra/core", @@ -604,7 +604,7 @@ "@id": "hydra:variable", "@type": "rdf:Property", "label": "variable", - "comment": "An IRI template variable", + "comment": "An Iri template variable.", "domain": "hydra:IriTemplateMapping", "range": "xsd:string", "isDefinedBy": "http://www.w3.org/ns/hydra/core", @@ -614,6 +614,7 @@ "@id": "hydra:resolveRelativeUsing", "@type": "rdf:Property", "label": "relative Uri resolution", + "comment": "Instructs on how to resolve relative Uri created by the Iri template resolution.", "domain": "hydra:IriTemplate", "range": "hydra:BaseUriSource", "isDefinedBy": "http://www.w3.org/ns/hydra/core", @@ -640,7 +641,7 @@ "@id": "hydra:LinkContext", "@type": "hydra:BaseUriSource", "label": "Link context", - "comment": "States that the link's context IRI, as defined in RFC 5988, should be used as the base Uri", + "comment": "States that the link's context IRI, as defined in RFC 5988, should be used as the base Uri.", "isDefinedBy": "http://www.w3.org/ns/hydra/core", "vs:term_status": "testing" }, @@ -705,7 +706,7 @@ "@type": "rdfs:Class", "subClassOf": "hydra:Resource", "label": "Header specification", - "comment": "Specifies a possible either expected or returned header values", + "comment": "Specifies a possible either expected or returned header values.", "isDefinedBy": "http://www.w3.org/ns/hydra/core", "vs:term_status": "testing" }, diff --git a/spec/latest/core/index.bs b/spec/latest/core/index.bs new file mode 100644 index 0000000..549fbb6 --- /dev/null +++ b/spec/latest/core/index.bs @@ -0,0 +1,5982 @@ +

+ + +Status of This Document {#sotd} +======================= +This specification was published by the [[!HydraCG]]. +It is not a W3C Standard, nor it is on the W3C Standards Track. +Please note that under the +*W3C Community Contributor License Agreement (CLA)* +there is a limited opt-out and other conditions apply. +Learn more about *W3C Community and Business Groups*. + +## Conventions ## {#conventions} + +Within this document, the following namespace prefix bindings are used: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PrefixNamespace
hydra:http://www.w3.org/ns/hydra/core#
rdf:http://www.w3.org/1999/02/22-rdf-syntax-ns#
rdfs:http://www.w3.org/2000/01/rdf-schema#
xsd:http://www.w3.org/2001/XMLSchema#
owl:http://www.w3.org/2002/07/owl#
vs:http://www.w3.org/2003/06/sw-vocab-status/ns#
dc:http://purl.org/dc/terms/
cc:http://creativecommons.org/ns#
schema:http://schema.org/
+ +Introduction {#introduction} +============ + +Note: This section is non-normative. + +Coping with the ever-increasing amount of data becomes increasingly +challenging. To alleviate the information overload put on people, +systems are progressively being connected directly to each other. +They exchange, analyze, and manipulate humongous amounts of data +without any human interaction. Most current solutions, however, +do not exploit the whole potential of the architecture of the World +Wide Web and completely ignore the possibilities offered by Linked Data +technologies. + +The combination of the REST architectural style, and the Linked +Data principles offer opportunities to advance the Web of machines +in a similar way that hypertext did for the human Web. Most +building blocks exist already and are in place, but they are rarely +used together. Hydra tries to fill that gap. It allows data +to be enriched with machine-readable affordances which enable interaction. +This not only addresses the problem that Linked Data is still mostly +read-only, but it also paves the way for a completely new breed +of interoperable Web APIs. The fact that it enables the creation +of composable contracts means that interaction models of Web APIs +can be reused at an unprecedented granularity. + +Hydra at a Glance {#hydra-at-a-glance} +================= + +Note: This section is non-normative. + +The basic idea behind Hydra is to provide a vocabulary which enables a +server to advertise valid state transitions to a client. A client can +then use this information to construct requests (i.e. compliant with +an HTTP protocol) which modify the server’s state so that a certain +desired goal is achieved. Since all the information about the valid state +transitions is exchanged in a machine-processable way at runtime +instead of being hardcoded into the client at design time, clients +can be decoupled from the server and adapt to changes more easily. + +The namespace of the Hydra core vocabulary +is `http://www.w3.org/ns/hydra/core#`, and the suggested prefix +is `hydra`. The figure below illustrates the vocabulary +(the figure’s goal is to show how Hydra is used rather than its precise +definition). + +The Hydra core vocabulary + +An alphabetical index of the classes and properties of Hydra +is given below. All the terms are hyperlinked to their detailed +description for quick reference. + +Using Hydra {#using-hydra} +=========== + +Throughout this section, a simple Web API featuring an issue tracker +will be used to illustrate how Hydra can be used. The Web API enables +its users to file new issues, modify or delete existing ones, and +to comment them. For the sake of simplicity, orthogonal aspects such +as authentication or authorization are not covered. + +## Adding Affordances to Representations ## {#adding-affordances-to-representations} + +The exemplary Web API has to expose representations of issues and +comments. To enable interaction with those resources, a client has +to know which operations the server supports. In human-facing +websites such affordances are typically exposed by links and forms +and described in natural language. Unfortunately, machines can not +interpret such information easily. The solution that presents itself +is to reduce the language to a few unambiguous concepts which are easily +recognizable by a machine client. Hydra formalizes such concepts. + +The simplest and most important affordance on the Web are hyperlinks. +Without them, it would be impossible to browse the Web. +Users typically select the link based on the text it is labeled with. +To give machines a similar understanding, links can be annotated +with a link relation type—a registered token or a URI identifying +the semantics of the link. The following example shows how such +a typed link is used in HTML to reference a stylesheet. + +
+ + <link href="http://www.example.com/styles.css" + rel="stylesheet" /> + +
+ +In Linked Data, the link relation type corresponds to the property itself. +An example in JSON-LD would thus look as follows. + +
+
+{
+    "urn:iana:link-relations:stylesheet": {
+        "@id": "http://www.example.com/styles.css"
+    }
+}
+
+
+ +Generally, a client decides whether to follow a link or not based on +the link relation (or property in the case of Linked Data) which +defines its semantics. There are however also clients such as Web crawlers +which simply follow every link intended to be dereferenced. In HTML this +usually means that all links in anchor elements +(the <a> tag) are followed, but most references in link +elements (the <link> tag), such as used in the example +above, are ignored. Since in RDF serializations no such distinction exists, +the best a client can do is to blindly try to dereference all URIs. +It would thus be beneficial to describe in a machine-readable manner +if a property represents a link intended to be dereferenced or +solely an identifier. Hydra's [=Link=] class does just that. It can be +used to define properties that represent dereferencable links. +In the exemplary Web API used throughout this section, it can be +used to define a property linking issues to their comments: + +
+
+{
+    "@context": "http://www.w3.org/ns/hydra/context.jsonld",
+    "@id": "http://api.example.com/vocab#comments",
+    "@type": "Link"
+}
+
+
+ +In the example above, a property identified with the URL +`http://api.example.com/vocab#comments` is defined to be +of the type [=Link=]. This is enough information for a client understanding +Hydra to know that the value of the `comments` property +in the following example is intended to be dereferenced. + +Note: It is recommended to dereference resources that are within an API's domain. +This may prevent possible issues with cross-site scripting or obtaining +resources which might have no meaning to the client or such that the client +would be unable to interpret. Still, there is no formal prohibition of +dereferencing resources linked with well-known properties, e.g. +*rdf:seeAlso*. + +
+
+{
+    "@context": {
+        "comments": "http://api.example.com/vocab#comments"
+    },
+    "@id": "http://api.example.com/an-issue",
+    "title": "An exemplary issue linking to its comments",
+    "comments": { "@id": "http://api.example.com/an-issue/comments" }
+}
+
+
+ +In the example above, the value of the `comments` property +is a JSON object with an `@id` member. This is JSON-LD's +convention to distinguish between strings and IRIs. By using JSON-LD's +type-coercion feature, the representation can be made even more idiomatic: + +
+
+{
+    "@context": {
+        "comments": {
+            "@id": "http://api.example.com/vocab#comments",
+            "@type": "@id"
+        }
+    },
+    "@id": "http://api.example.com/an-issue",
+    "title": "An exemplary issue linking to its comments",
+    "comments":
+        "http://api.example.com/an-issue/comments"
+}
+
+
+ +While links are enough to build read-only Web APIs, more powerful +affordances are required to build read-write Web APIs. Thus, Hydra +introduces the notion of operations. Simply speaking, an +[=Operation=] represents the information necessary for a client +to construct valid HTTP requests in order to manipulate the server's +resource state. As such, the only required property of an +[=Operation=] is its [=method=]. Optionally, it is also possible +to describe what information the server [=expects=] or [=returns=], +including additional information about response status codes that +might be returned. This helps a developer to understand what to expect +when invoking an operation. This information has, however, +not to be considered as being complete; it is merely a hint. +Developers should, e.g., expect that other status codes might be returned +and program their clients accordingly. + +The following example illustrates how representations can be +augmented with information that enables clients to interact with +them. + +
+
+{
+    "@context": "http://www.w3.org/ns/hydra/context.jsonld",
+    "@id": "/an-issue",
+    "title": "An exemplary issue representation",
+    "description": "This issue can be deleted with an HTTP DELETE request.",
+    "operation": [
+        {
+            "@type": "Operation",
+            "method": "DELETE"
+        }
+    ]
+}
+
+
+ +The example above references Hydra's context to map properties such +as [=operation=] and [=method=] and values like [=Operation=] to URLs +that unambiguously identify these concepts. It would be similarly valid +JSON-LD if these mappings would be directly embedded into the representation +or if the full URLs would be used instead. Typically, however, the context +is the same for a lot of representations in a Web API and it thus makes +sense to reduce the response size by leveraging a remote context that +can easily be cached by a client. + +Note: It is worth mentioning that due to the fact that Hydra is built on +RDF, which is a graph, it may happen that a related resource +(an object of the relation) may not be fully described in the +resource's payload. + +In several circumstances (i.e. payload terms defined in +[=ApiDocumentation|API documentation=] sa described in +[[#documenting-a-web-api]] or [=IriTemplate=] +expected as a related resource as described in +[[#templated-links|Templated Links]]) client may +discover no additional statements describing it. These rules should +be considered by the client in following scenarios: + +- in case of an object expected to be a hypermedia resource does not have + all the necessary statements for which it is a subject, the client + SHOULD look in the [=ApiDocumentation|API documentation=] for more details +- in case the mentioned object, after consulting + an [=ApiDocumentation|API documentation=], still does not have + all the necessary statements for which it is a subject and both + mentioned object's Url and Url of the initially obtained resource + has the same scheme and authority (by means of [[!RFC3986]] + sections 3.1 and 3.2), the client SHOULD dereference that URL. + If the resource does not have the same scheme and authority the client + MAY chose to dereference it (for example if the resource originates + from another API well-known to the client) +- in case the mentioned object still does not have all the necessary + statements for which it is a subject (i.e. dereferencing it failed + or statements are missing), the client SHOULD either ignore the whole + statement (i.e. for display purposes) or throw an exception + (i.e. an [=IriTemplate=] is about to be resolved and dereferenced) + +Example of each of the situations are as follows: + +
+ +HTTP/1.1 200 OK +Content-Type: application/ld+json +Link: <http://api.example.com/doc/>; rel="http://www.w3.org/ns/hydra/core#apiDocumentation" + +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@graph": [{ + "@id": "http://api.example.com/attachments", + "@type": "hydra:Collection", + "api:attachmentByIssue": "api:AttachmentByIssueTemplate" + }, { + "@id": "http://api.example.com/issues", + "@type": "hydra:Collection", + "api:issueByName": "api:IssueByNameTemplate" + } +} + +
+HTTP/1.1 200 OK
+Content-Type: application/ld+json
+
+{
+    "@context": "http://www.w3.org/ns/hydra/context.jsonld",
+    "@graph": [{
+        "@id": "api:AttachmentByIssueTemplate",
+        "@type": "hydra:IriTemplate",
+        "template": "http://api.example.com/attachments/{issue}",
+        ...
+    }]
+}
+
+
+ +where: + +- resource `http://api.example.com/attachments` should have + an [=IriTemplate=] available as there is a complete definition + of the template available at `http://api.example.com/doc/` +- resource `http://api.example.com/issues` should not have + an IRI template exposed as there are no additional details available, + neither in the initial resources' payload nor in the API documentation + +Note: Keep in mind that any resource described by any hypermedia control +may fail at runtime due to various reasons. Operation details +such as [=returns=] or [=possibleStatus=] may also vary at runtime, +which means client SHOULD always verify received payloads at runtime. + +## Documenting a Web API ## {#documenting-a-web-api} + +In Web APIs, most representations are typically very similar. +Furthermore, resources often support the same operations. It thus +makes sense, to collect this information in a central documentation. +Traditionally, this has been done in natural language which forces +developers to hardcode that knowledge into their clients. Hydra +addresses this issue by making the documentation completely +machine-processable. The fact that all definitions can be identified +by URLs enables reuse at unprecedented granularity. + +Hydra's [=ApiDocumentation=] class builds the foundation for +the description of a Web API. As shown in the following example, +Hydra describes an API by giving it a title, a short description, and +documenting its main entry point. Furthermore, the classes known to +be supported by the Web API and additional information about status +codes that might be returned can be documented. This information +may be used to automatically generate documentations in natural +language. + +
+
+{
+    "@context": "http://www.w3.org/ns/hydra/context.jsonld",
+    "@id": "http://api.example.com/doc/",
+    "@type": "ApiDocumentation",
+    "title": "The name of the API",
+    "description": "A short description of the API",
+    "entrypoint": "URL of the API's main entry point",
+    "supportedClass": [
+        // "... Classes known to be supported by the Web API ..."
+    ],
+    "possibleStatus": [
+        // "... Statuses that should be expected and handled properly ..."
+    ]
+}
+
+
+ +In Linked Data, properties are, just as everything else, identified +by IRIs and thus have global scope which implies that they have +independent semantics. In contrast, properties in data models as +used in common programming languages are class-dependent. Their +semantics depend on the class they belong to. In data models classes +are typically described by the properties they expose whereas in +Linked Data properties define to which classes they belong. If no +class is specified, it is assumed that a property may apply to every +class. + +These differences have interesting consequences. For example, the +commonly asked question of which properties can be applied to an +instance of a specific class can typically not be answered for +Linked Data. Strictly speaking, any property which is not explicitly +forbidden could be applied. This stems from the fact that Linked Data +works under an open-world assumption whereas data models used by +programmers typically work under a closed-world assumption. The +difference is that when a closed world is assumed, everything that +is not known to be true is false or vice-versa. With an open-world +assumption the failure to derive a fact does not automatically imply +the opposite; it embraces the fact that the knowledge is incomplete. + +Since Hydra may use classes to describe the information expected or +returned by an operation, it also defines a concept to describe the +properties known to be supported by a class. The following example +illustrates this feature. Instead of referencing properties directly, +[=supportedProperty=] references an intermediate data structure, +namely instances of the [=SupportedProperty=] class. This makes +it possible to define whether a specific property is required or +whether it is read-only or write-only depending on the class it is +associated with. + +
+
+{
+    "@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?"
+            "writable": true // "Can the client change the property's value?"
+        }
+    ]
+}
+
+
+ +All instances of a specific class typically support the same operations. +Hydra therefore features a [=supportedOperation=] property which defines +the operations supported by all instances of a class. + +
+
+{
+    "@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 ..."
+    ],
+    "supportedOperation": [
+        // "... Operations known to be supported by instances of the class ..."
+    ]
+}
+
+
+ +The same feature can be used to describe the operations supported +by values of a [=Link=] property. This is often helpful when +certain operations depend on the permissions of the current user. It +makes it, e.g., possible to show a "delete" link only if the current +user has the permission to delete the resource. Otherwise, the link +would simply be hidden in the representation. + +Example shown below describes the operation's expected and returned +value as a dereferencable resource (an RDF resource of a given class), +but the vocabulary is not limited to only those originating +from RDF and is enabled to other types of resources. +Please note that in case of multiple either returned or expected types +provided, client SHOULD assume the set includes any of the types, +but not limited to those types and client SHOULD interpret a received +payload at runtime for possible discrepancies. + +
+
+{
+    "@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": "Operation",
+            "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 ..."
+            ]
+        }
+    ]
+}
+
+
+ +Note: It is worth to mention that Hydra comes with a notion +of a dereferenceability promise, which means that resources marked +with a [=Resource=] class can be safely dereferenced by a client. +Unfortunately, the way how the Word Wide Web works it is impossible to +guarantee that the resource finally will be obtained. + +In addition to [=expects|expected=]/[=returns|returned=] resources, +it is also possible to express similar features for headers with +[=returnsHeader=] and [=expectsHeader=] predicates which provides +a simple set of header names. Client SHOULD apply respective header +semantics when creating or receiving a request natural for the protocol in use. + +
+
+{
+    "@context": "http://www.w3.org/ns/hydra/context.jsonld",
+    "@id": "http://api.example.com/doc/#comments",
+    "@type": "Link",
+    "supportedOperation": [
+        {
+            "@type": "Operation",
+            "method": "POST",
+            "expects": "http://api.example.com/doc/#Comment",
+            "returns": "http://api.example.com/doc/#Comment",
+            "returnsHeader": [
+                "Content-Type",
+                "Content-Length"],
+            "expectsHeader": [
+                "Authorization"
+            ]
+        }
+    ]
+}
+
+
+ +The example above enable an HTTP client to prepare a proper cross-site +pre-flight request, so the server exposes enlisted headers for the client. +The client is also aware of the user authentication requirement necessary +for the operation invocation. + +For more complex scenarios it is also possible to expand selected header +specification with both name and possible values, i.e. when defining +expected *Content-Type* values of resources that can be uploaded. +In case multiple possible values are provided, client SHOULD assume +that the set includes any of the values, but not limited to those values. +In order to change that default behavior it is possible to use [=closedSet=] +predicate on the header specification indicating that the set of provided +values is, well, closed and no other values are available. In both cases +the client SHOULD interpret a received payload at runtime for possible +discrepancies. + +
+
+{
+    "@context": "http://www.w3.org/ns/hydra/context.jsonld",
+    "@id": "http://api.example.com/doc/#comments",
+    "@type": "Link",
+    "supportedOperation": [
+        {
+            "@type": "Operation",
+            "method": "POST",
+            "expects": "http://api.example.com/doc/#Upload",
+            "returns": "http://api.example.com/doc/#Comment",
+            "returnsHeader": [
+                {
+                    "headerName": "Content-Type",
+                    "possibleValue": ["text/turtle", "application/ld+json"]
+                }
+                "Content-Length"
+            ],
+            "expectsHeader": [
+                "Authorization",
+                {
+                    "headerName": "Content-Type",
+                    "possibleValue": ["image/gif", "image/png"]
+                }
+            ]
+        }
+    ]
+}
+
+
+ +To wrap up everything altogether, it is also possible to attach atomic +operations supported by, well, supported property itself. This might +come in handy for scenarios, when resource can be partially modified. +It can be achieved with two approaches, both having advantages and +disadvantages. + +First approach would involve adding a [=supportedOperation=] to the +intermediate structure of [=SupportedProperty=]. +This way prevents from leaking API specific features from the API itself +to i.e. externally defined properties. Data aggregators won't assume that +each instance with a given property could have such an operation. + +Another approach would require the API to elevate a specific property +to [=Link=], which can accept a [=supportedOperation=]. This +is more intuitive in APIs operating with internally used vocabularies +where assumption that every instance with that very specific property +has the operation attached available. + +Direct usage of [=supportedOperation=] on *rdf:Property* +without elevating it to the [=Link=] SHOULD NOT be implemented as clients +may not discover such a construct correctly. + +Note: These are the simple example scenarios and possible usages are not +limited to those described above. + +Due to the fact an [=ApiDocumentation=] as all other resources may fail +at runtime, it is important to take countermeasures. A simple strategy +to try to recover from such a situation would be to reload +the [=ApiDocumentation=] and redo all pre-computations that were +based on the [=ApiDocumentation=] (or at least those that lead +to the current failure). Another, simpler approach would require +an application to show an error message with option to return +to a previous or home screen. + +Hydra also allows enriching both [=ApiDocumentation=] and +hypermedia controls with human-readable descriptions by applying +[=title=] and [=description=] (as shown in the examples above). +The former states a name of such a decorated element that could +be displayed as a label. The latter provides its description +to be presented i.e. as a hint. + +Aforementioned [=title=] and [=description=] SHOULD take precedence +over standard *rdfs:label* and *rdfs:comment*. + +There is one more feature related to how Linked Data works. Consider the +example below written in turtle syntax: + +
+ +# An example API documentation itself with all the standard bits +@base <http://some.app/> . +@prefix api: <http://some.api/> . +@prefix ex: <http://ontology.example/> . +@prefix hydra: <http://www.w3.org/ns/hydra/core> . +@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . +<api> + a hydra:ApiDocumentation ; + hydra:supportedClass api:ClassOne, api:ClassTwo . + +# Anything else +ex:SomeType a rdfs:Class . + +
+ +...and how it could be transformed with JSON-LD framing process: + +
+
+{
+    "@context": { ... },
+    "@graph": [
+        {
+            "@id": "http://some.app/api",
+            "@type": "hydra:ApiDocumentation",
+            "hydra:supportedClass": [
+                {
+                    "@id": "api:ClassTwo"
+                },
+                {
+                    "@id": "api:ClassOne"
+                }
+            ]
+        }
+    ]
+}
+
+
+ +As you can see, additional details about *ex:SomeType* went +missing, while this shouldn't happen. The fact that the IRI mentioned +is an *rdfs:Class* may be meaningful for a correct interpretation +of the received payload and this is a sole reason of why a Client +SHOULD NOT disregard other parts of the payload that are not directly +related to the API documentation or other hypermedia controls. + +## Discovering a Hydra-powered Web API ## {#discovering} + +The first step when trying to access a Web API is to find an entry +point. Typically, this is done by looking for a documentation on the +API publisher's homepage. Hydra enables the API's main entry point +to be discovered automatically if the API publisher marks his +responses with a special HTTP Link Header as defined in [[!RFC8288]]. +A Hydra client would look for a Link Header with a relation type +`http://www.w3.org/ns/hydra/core#apiDocumentation` (this is +the IRI identifying the [=apiDocumentation=] property). + +In the following example, a Hydra client simply accesses the +homepage of an API publisher (`http://www.example.com/`) +to find the entry point of its API. A client may use an HTTP GET or +HEAD request. The difference between the two is that the former may +return a message-body in the response whereas the latter will not; +otherwise they are identical. + +
+
+HEAD / HTTP/1.1
+Host: www.example.com
+
+ +HTTP/1.1 200 OK +... +Content-Type: text/html; charset=utf-8 +Link: <http://api.example.com/doc/>; rel="http://www.w3.org/ns/hydra/core#apiDocumentation" + +
+ +The response in the example above contains an HTTP Link Header +pointing to `http://api.example.com/doc/`. Retrieving that resource, +the client would obtain a [=ApiDocumentation|Hydra API documentation=] +defining the API's main entry point: + +
+
+GET /doc/ HTTP/1.1
+Host: api.example.com
+Accept: application/ld+json
+
+
+HTTP/1.1 200 OK
+...
+Content-Type: application/ld+json
+
+{
+    "@context": "http://www.w3.org/ns/hydra/context.jsonld",
+    "@id": "http://api.example.com/doc/",
+    "title": "The example.com API",
+    "entrypoint": "http://api.example.com/",
+    ...
+}
+
+
+ +Note: Please note that in some cases the entry point will already be +known to the client. Thus, the discovery of the API documentation +using HTTP Link Headers may not be necessary as the concepts +used in responses from the API will dereference to their documentation. + +In another scenario the [=ApiDocumentation=] would be discovered from +a bookmarked resource's representation. +The [=ApiDocumentation|API implementation=] SHOULD emit the HTTP [=Link=] +header on every API response, making the [=ApiDocumentation=] (and entry +points it defined) discoverable all the time. + +
+
+GET /api/items HTTP/1.1
+Host: api.example.com
+Accept: application/ld+json
+
+ +HTTP/1.1 200 OK +... +Content-Type: application/ld+json +Link: <http://api.example.com/doc/>; rel="http://www.w3.org/ns/hydra/core#apiDocumentation" + +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api/items", + "title": "Items collection", + ... +} + +
+ +## Api versions ## {#api-versions} + +It is common to provide a separate API address after a breaking changes +update. This prevents current clients not to get broken as these may not +support these changes. + +With hypermedia provided in each response payload, it may be unnecessary +to provide such an alternative API. This is due to fact the client follows +what the server provides and with proper margin for errors implemented +within that client, even breaking changes can be published on the fly. + +Still, Hydra does neither have any special support for API versions, nor +prevents them. It's fully an implementers decision on if and how +to provide the API features. + +Advanced Concepts {#advanced-concepts} +================= + +## Collections ## {#collections} + +In many situations, it makes sense to expose resources that reference +a set of somehow related resources. Results of a search query or +entries of an address book are just two examples. To simplify such +use cases, Hydra defines the two classes [=Collection=] and +[=PartialCollectionView=]. + +A [=Collection=] can be used to reference a set of resources +as follows: + +
+
+{
+    "@context": "http://www.w3.org/ns/hydra/context.jsonld",
+    "@id": "http://api.example.com/an-issue/comments",
+    "@type": "Collection",
+    "totalItems": 4980,
+    "member" : [
+        {
+            "@id": "/comments/429"
+        },
+        {
+            "@id": "/comments/781",
+            "title": "Properties may be embedded directly in the collection"
+        },
+        ...
+    ]
+}
+
+
+ +As shown in the example above, member items can either consist of +solely a link or also include some properties. In some cases embedding +member properties directly in the collection is beneficial as it may +reduce the number of HTTP requests necessary to get enough information +to process the result. + +Since collections may become very large, Web APIs often chose to +split a collection into multiple pages. In Hydra, that can be achieved +with a [=PartialCollectionView=]. It describes a specific +view on the collection which represents only a subset of the collection's +members. A [=PartialCollectionView=] may contain links to the +[=first=], [=next=], [=previous=], and [=last=] +[=PartialCollectionView=] which allows a client to find all members +of a [=Collection=]. + +
+
+{
+    "@context": "http://www.w3.org/ns/hydra/context.jsonld",
+    "@id": "http://api.example.com/an-issue/comments",
+    "@type": "Collection",
+    "totalItems": 4980,
+    "member": [
+        // "... a subset of the members of the Collection ..."
+    ],
+    "view": {
+        "@id": "http://api.example.com/an-issue/comments?page=3",
+        "@type": "PartialCollectionView",
+        "first": "/an-issue/comments?page=1",
+        "previous": "/an-issue/comments?page=2",
+        "next": "/an-issue/comments?page=4",
+        "last": "/an-issue/comments?page=498"
+    }
+}
+
+
+ +Note: It is worth to mention that all those links are optional, +and it is up to server whether to provide these links or not. + +## Member assertions ## {#member-assertions} + +A [=memberAssertion=] (formerly `manages`) is a way to declare additional, +implicit statements about members of a [[#collections|collection]]. +Statements which may otherwise be missing from the respective member +resources inlined in a collection's representation. + +
+
+{
+    "@context": "http://www.w3.org/ns/hydra/context.jsonld",
+    "@id": "http://api.example.com/an-issue/comments",
+    "@type": "Collection",
+    "memberAssertion": {
+        "subject": "http://api.example.com/an-issue",
+        "property": "http://api.example.com/vocab#comment"
+    },
+    "member": [
+        {
+            "@id": "/comments/429"
+        }
+    ]
+}
+
+
+ +In the above example, adding a `memberAssertion` node to the collection +instructs the client that every member of this collection is linked +to the `subject` by the `property`. It could be written as a SPARQL +triple pattern below, where `?m` would be substituted by each member +of the collection. + + + <http://api.example.com/an-issue> <http://api.example.com/vocab#comment> ?m + + +A [=memberAssertion=] MUST use two and only two of the [=subject=], +[=property=] and [=object=] predicates. The [=memberAssertion=] predicate +MAY have more than one such blocks, each expressing different relations +between the collection members and other resources. + +Note: It's important to point out that the [=subject=], [=property=] +and [=object=] predicates are defined within the Hydra namespace +and are not [[!RDF-Schema|rdfs]] terms. + +It is also possible to use [=memberAssertion=] predicate on the +API documentation level, by attaching this predicate to subclasses +of the [=Collection=], like in the example below. Clients would +understand that all members of collections which are instances +of `api:UserCollections` would in fact have `rdf:type api:User`. + +
+
+{
+    "@context": [
+        "http://www.w3.org/ns/hydra/context.jsonld",
+        { "api": "http://api.example.com/api/documentation#" }
+    ],
+    "@id": "http://api.example.com/api/documentation",
+    "@type": "ApiDocumentation",
+    "supportedClass": ["api:User", "api:UserCollection"],
+    "api:UserCollection": {
+        "subClassOf": "Collection",
+        "memberAssertion": {
+            "property": "rdf:type",
+            "object": "api:User"
+        },
+    }
+}
+
+
+ +It is worth to mention that a strongly typed collection instance can have +its own member assertions. In such a scenario, both +[=ApiDocumentation|API documentation=] level and instance +level assertions should be combined as neither makes the other obsolete. + +More complex scenario would involve a class hierarchy, in which each class +can carry additional member assertions compared to it's base class. +To discover all available member assertion blocks client SHOULD traverse +whole class hierarchy to gather all the member assertions. In order +to take such a burden from clients it is strongly recommended providing +all member assertion blocks to be provided on each class level including +its base class blocks, so the client does not have to perform +this traversing behavior. + +## Templated Links ## {#templated-links} + +Sometimes, it is impossible for a server to construct a URL because +the URL depends on information only known by the client. A typical +use case are URLs which enable a client to query the server. In such +a case, the server cannot construct the URL because it does not know +the query the client is interested in. What the server can do however, +is to give the client a template to construct such a URL at runtime. +In Hydra, the [=IriTemplate=] class is used to do so. + +An [=IriTemplate=] consists of a [=template=] literal and a set +of [=mappings=]. Each [=IriTemplateMapping=] maps a +[=variable=] used in the template to a [=property=] and may +optionally specify whether that variable is [=required=] or not. +The syntax of the template literal is specified by its datatype and +defaults to the [[!RFC6570]] URI Template syntax, which can be +explicitly indicated by [=Rfc6570Template=]. + +
+
+{
+    "@context": "http://www.w3.org/ns/hydra/context.jsonld",
+    "@type": "IriTemplate",
+    "template": "http://api.example.com/issues{?q}",
+    "variableRepresentation": "hydra:BasicRepresentation",
+    "mapping": [
+        {
+            "@type": "IriTemplateMapping",
+            "variable": "q",
+            "property": "hydra:freetextQuery",
+            "required": true
+        }
+    ]
+}
+
+
+ +The example above maps the variable `q` to Hydra's [=freetextQuery=] +property and marks it as required. As its name suggests, +the [=freetextQuery=] property can be used for free text queries. + +A template syntax only details how to fill out simple string values, +but not how to derive such string values from typed values, +language-tagged strings, or IRIs. Hydra addresses this by +specifying how such values are to be serialized as strings. The +serialization of an [=IriTemplate's=] variables can be described +by setting the [=variableRepresentation=] property to +[=BasicRepresentation=] or [=ExplicitRepresentation=]. The +[=BasicRepresentation=] represents values by their lexical form. It +omits type and language information and does not differentiate between +IRIs and literals. The [=ExplicitRepresentation=], on the other +hand, includes type and language information and differentiates +between IRIs and literals by serializing values as follows: + +- IRIs are represented as-is +- literals, i.e., (typed) values and language-tagged strings are + represented by their lexical form, surrounded by a single pair of + doubles quotes (`"`) +- if a literal has a language, a single `@` symbol is + appended after the double-quoted lexical form, followed by a + non-empty [[!BCP47]] language code +- if a literal has a type, two *caret* symbols (`^^`) are appended + after the double-quoted literal, followed by the full datatype IRI + +In both representations characters MUST NOT be escaped. In case the +representation format is not explicitly described, clients SHOULD +use the [=BasicRepresentation=] by default. + +

+Warning: Although [=ExplicitRepresentation=] +use of `@` and `^^` is similar, it is *not* the same as the +[[!Turtle]] representation for literals. Turtle literals require escaping +of special characters, surround datatype IRIs with angular brackets +(< and >), and also allow single quotes (`'`) to indicate literals. +The [=ExplicitRepresentation=] values must not be escaped, +IRIs must not be surrounded by any character, and only double quotes +can indicate literals. +

+ +Below are some example values serialized in the different +representations as well as the result of expanding the IRI template +`http://example.com/find/{value}` with the respective value. + + + +Similar to how Hydra's [=Link=] class allows the definition of +properties that represent hyperlinks as described in +[[#adding-affordances-to-representations]], the [=TemplatedLink=] class +allows the definition of properties whose value are IRI templates. +Hydra predefines one such property, namely the [=search=] property which +can be used to document available search interfaces. + +
+
+    {
+        "@context": "http://www.w3.org/ns/hydra/context.jsonld",
+        "@id": "hydra:search",
+        "@type": "hydra:TemplatedLink"
+    }
+
+
+ +IRI expansion should be performed with respect to the specification +behind the IRI template type ([[!RFC6570]] by default), and the product +of this process SHOULD be an IRI. When the produced IRI is relative, +the client SHOULD stick to [[!RFC3986]] sections 5.1.3 and 5.1.4 +to be compatible with most RDF serializations that support relative IRIs. +Still, it may be preferred to use another base URI for the expansion +process, which makes the [=resolveRelativeUsing=] term useful. It allows +to switch the IRI template expansion algorithm, so the base URI +is established using current link context, which is a subject +of the relation pointing to an [=IriTemplate=] instance. In case +that subject is a relative URI, default behavior SHOULD be used as fallback. + +The example below allows to make the product of an IRI template +expansion relative to the `http://api.example.com/an-issue/` resource +by using it as its base URI, which further enables the `some:operation` +to be moved to i.e. [=ApiDocumentation|API documentation=] level rather +to inline it. + +
+
+{
+    "@context": "http://www.w3.org/ns/hydra/context.jsonld",
+    "@id": "http://api.example.com/an-issue/",
+    "@type": "Collection",
+    "some:operation": {
+        "@type": "IriTemplate",
+        "template": "{id}",
+        "resolveRelativeUsing": "LinkContext",
+        "variable": "id",
+        "mapping": {...}
+    }
+}
+
+
+ +When constructed, the IRI would effectively become similar +to `http://api.example.com/an-issue/1234`, with the relative part +`{id}` appended to the link context URL. + +## IRI template operations ## {#iri-template-operations} + +There are circumstances in which client would like to perform an operation +not knowing the final IRI of the resource to be called. This case +is especially in force when working with collections - client may want +to add a new collection member, or it may need to provide more details +while searching with other protocol's method (i.e. POST instead of GET +in case of an HTTP). + +This is achievable by attaching a [=supportedOperation=] to the property +that connects a subject of that relation with its [=IriTemplate=] +as described in the previous part of this document. Please note that +client is still allowed to use the defined link and custom operation's +method is optional. + +
+
+{
+    "@context": "http://www.w3.org/ns/hydra/context.jsonld",
+    "@id": "http://api.example.com/api-documentation",
+    "@type": "ApiDocumentation",
+    "api:search": {
+        "@type": "Link",
+        "rdfs:subClassOf": "search",
+        "supportedOperation": {
+            "@type": "SupportedOperation",
+            "method": "POST"
+        }
+    }
+}
+
+
+{
+    "@context": "http://www.w3.org/ns/hydra/context.jsonld",
+    "@id": "http://api.example.com/issues",
+    "@type": "Collection",
+    "api:search": {
+        "@type": "IriTemplate",
+        "template": "/issues?search={name}",
+        "mapping": { ... }
+    }
+}
+
+
+ +The example above allows client to either invoke an HTTP GET or POST +call on `http://api.example.com/issues?search=search_string` resource. + +
+
+{
+    "@context": "http://www.w3.org/ns/hydra/context.jsonld",
+    "@id": "http://api.example.com/api-documentation",
+    "@type": "ApiDocumentation",
+    "api:find": {
+        "supportedOperation": {
+            "@type": "SupportedOperation",
+            "method": "POST"
+        }
+    }
+}
+
+
+{
+    "@context": "http://www.w3.org/ns/hydra/context.jsonld",
+    "@id": "http://api.example.com/issues",
+    "@type": "Collection",
+    "api:search": {
+        "@type": "IriTemplate",
+        "template": "/issues?find={name}",
+        "mapping": {...}
+    }
+}
+
+
+ +The example above allows client to invoke only an HTTP POST +call on `http://api.example.com/issues?find=search_string` resource as +the described relation of `find` is not a [=Link=]. + +## Supported property data source ## {#supported-property-data-source} + +There are circumstances in which an API would like to inform a client on +when to obtain values to feed data structures with details. Having all the +necessary components like supported property, collection and IRI templates, +it is possible to drive the client and direct it with links and operations +to the data sources. + +It is doable by attaching either a [=collection=] or [=search=] +predicate to instance of [=supportedProperty=] or to [=property=]. +In such case client SHOULD assume that the relation leads to +the collection of values compatible with the supported property's range +and can be used to feed data structures with the supported property. +It is recommended (but not mandatory) to use [=freetextQuery=] +variable mapping in case of the [=search=] predicate as it has a +well-defined semantics and takes the burden of interpretation from +the client. + +While it is possible to provide such links in both +[=ApiDocumentation|API documentation=] and within the received payload, +client SHOULD use the latter link first if applicable. +This is due to the fact the server may want to put additional +context to narrow the collection of viable values. Redefinition does not +make the more general one obsolete though and can be used as a fallback. + +
+
+{
+    "@context": "http://www.w3.org/ns/hydra/context.jsonld",
+    "@type": "ApiDocumentation",
+    "supportedClass": {
+        "@id": "schema:Event",
+        "supportedProperty": {
+            "property": "schema:actor",
+            "search": {
+                "template": "/api/user{?search}",
+                "mapping": {
+                    "variable": "search",
+                    "property": "freetextQuery"
+                }
+            }
+        }
+    },
+    ...
+}
+
+
+ +The example above instructs a client that every resource of type +`schema:Event` can have a relation of `schema:actor`, the objects +of which the client can obtain using the search link provided. + +## Description of HTTP Status Codes and Errors ## {#description-of-errors} + +In case of the HTTP protocol, status codes have well-defined semantics +and can be used to signal the outcome of an operation. Unfortunately, +however, HTTP status codes by themselves are often not specific enough, +making it difficult to understand the real cause of an error. For instance, +a `429 Too Many Requests` response is rarely informative enough by itself. +To address this issue, Hydra defines a [=Status=] class which allows +additional information to be associated with the HTTP status code. + +
+
+{
+    "@context": "http://www.w3.org/ns/hydra/context.jsonld",
+    "@type": "Status",
+    "statusCode": 429,
+    "title": "Too Many Requests",
+    "description": "A maximum of 500 requests per hour and user is allowed.",
+    ...
+}
+
+
+ +An [=ApiDocumentation=] or an [=Operation=] may document the +status codes that might be returned by the server using the +[=possibleStatus=] property as described in [[#documenting-a-web-api]]. +This allows a developer to understand what to expect when invoking +an operation. It has, however, not to be considered as an extensive +list of all potentially returned status codes; it is merely a hint. +Developers should expect to encounter other HTTP status codes as well. + +A server may also return a [=Status=] directly in a response. +When doing so, it often makes sense to subclass the [=Status=] +to make its semantics more explicit. Hydra defines just one such subclass, +namely the [=Error=] class. This provides an extensible framework +to communicate error details to a client. + +Furthermore, a [=Status=] or [=Error=] returned by the server can also +be given an identifier. When dereferenced, the [=Error=] resource +can provide more detailed information or possible ways to resolve +the problem, if applicable. + +Finally, the server SHOULD provide error descriptions using an [[!RFC7807]] +standard by using an `application/problem+json` response. When doing so, +the server also MUST provide an additional header pointing to either +the built-in Hydra `http://www.w3.org/ns/hydra/error` context +or any JSON-LD context that maps the terms `type`, `title`, `detail`, +`status` and `instance` the same way as the standard one. + +
+ +HTTP/1.1 400 Bad Request +Content-Type: application/problem+json +Link: <http://www.w3.org/ns/hydra/error>; rel="http://www.w3.org/ns/json-ld#context" + +{ + "type": "https://example.com/probs/out-of-credit", + "@type": "http://www.w3.org/ns/hydra/core#Error", + "title": "You do not have enough credit.", + "detail": "Your current balance is 30, but that costs 50.", + "instance": "/account/12345/msgs/abc", + "balance": 30, + "accounts": [ + "/account/12345", + "/account/67890" + ] +} + +
+ +While the built-in context makes the response fully compatible with +the mentioned specification, properties not defined in the standard +Hydra's error context won't be visible for Hydra aware processors. +To overcome this, it is possible to declare a custom context pointed +the same way, that would combine standard Hydra's standard error context +and an additional JSON-LD context with either the `@vocab` or custom +property mappings telling the processor on how to interpret those custom +error properties. + +Resources provided may have an additional hint pointing to an [=Error=] +type like in the example above, but it is not mandatory to do so as all +resources described with `application/problem+json` are considered +[=Error=]. + +Note: It is worth to mention that it may happen (i.e. due to proxy behavior) +the value of the [=status=] property will differ to the one received +from the protocol layer. + +
+
+HTTP/1.1 400 Bad Request
+Content-Type: application/ld+json
+
+{
+    "@context": "http://www.w3.org/ns/hydra/context.jsonld",
+    "@type": "Error",
+    "@id": "http://api.example.com/error-details/1234",
+    "title": "An error occurred",
+    "description": "Typically, a specialization of this class is used in practice.",
+    ...
+}
+
+
+ +## Client initiated pagination ## {#pagination} + +There are situations when a client would like to provide a specific +collection limitations, i.e. by providing query-language like member +offset and limit, or some specific page index and number of members +per page. This is doable with [=offset=]/[=limit=] +or [=pageIndex=]/[=limit=] predicates. + +With those, it is possible to bind a template variables mapped +with externally obtained values (i.e. user interaction) the same way +as with other mappings. + +While the predicates enlisted above accepts non-negative integer +numbers, there is also a possibility of providing a custom page +reference expressed via [=pageReference=] predicate. It is possible +to provide a custom page identifier (i.e. a GUID or a letter) +instead of a number. + +## Extensions ## {#extensions} + +While Hydra Core Vocabulary allows addressing many usage scenarios, +not every aspect of API behavior can be covered. This +applies especially to querying, resource projection or data structure +description. This is due to fact that Hydra is meant to be as light +as possible forcing to drop some features out of its scope. + +That is why there is a possibility of hinting a client on what kind +of extensions may be found or used in the received payloads. +After discovering an [=extension=] predicate in the +[=ApiDocumentation|API documentation=], client can assume additional +details are available described with complementary vocabularies. + +
+
+{
+    "@context": "http://www.w3.org/ns/hydra/context.jsonld",
+    "@id": "http://api.example.com/doc/",
+    "@type": "ApiDocumentation",
+    "title": "The name of the API",
+    "description": "A short description of the API",
+    "entrypoint": "URL of the API's main entry point",
+    "extension": "http://www.w3.org/ns/shacl#",
+    ...
+}
+
+
+ +It is up to the used vocabulary to define how these additional details +should be interpreted. In case client does not recognize these extensions, +additional details should be ignored and base Hydra interpretation +should be in force. + +Server SHOULD NOT use extensions to add statements that are in +contradiction to base Hydra interpretation, so the client is not confused. +Server SHOULD also keep multiple extensions describing adequate +knowledge in line regarding their description (i.e. data structure +descriptions in various vocabularies should not cause differences). + +Client can express its preferences through the `Prefer` HTTP header +by pointing the preferred extensions via IRIs as on the example below. +The client SHOULD use the `Prefer` HTTP header [[!RFC7240]] with +the `hydra.extension` preference as an `iri` attribute having +the IRI of the extension as value to hint the server about the extension +it supports. Multiple preferences can be expressed by providing multiple +`Prefer` header values. + +
+
+GET http://api.example.com/api/people HTTP/1.1
+Prefer: hydra.extension; iri="http://schema.org/"
+
+
+ +Server MUST implement `Prefer` header handling according to +the [[!RFC7240]] and implementers should proceed with caution. + +Classes {#classes} +======= + +## hydra:ApiDocumentation ## {#class-ApiDocumentation} + + + + + + + + + + + + + +
Name:ApiDocumentation
Summary:The Hydra API documentation class.
Sub-class of:[=Resource=]
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api?documentation", + "@type": "ApiDocumentation", + "entrypoint": "http://api.example.com/api", + "extension": "https://w3id.org/hydra/extension#shacl", + "supportedClass": [ + { + "@id": "http://api.example.com/vocab#User", + "title": "User", + "description": "Describes a system user.", + "supportedOperation": [ + { + "method": "PUT", + "title": "Create new user", + "description": "Creates a brand new user.", + "expects": "http://api.example.com/vocab#User", + "returns": "http://api.example.com/vocab#User", + "returnsHeader": [ + { + "headerName": "Content-Type", + "possibleValue": ["text/turtle", "application/ld+json"], + "closedSet": true + } + "Content-Length" + ], + "expectsHeader": [ + "Authorization", + { + "headerName": "Content-Type", + "possibleValue": ["image/gif", "image/png"], + "closedSet": true + } + ] + } + ], + "supportedProperty": [ + { + "property": "http://api.example.com/vocab#login", + "writable": true, + "readable": true, + "required": true + } + ] + } + ] +} + +
+ +## hydra:BaseUriSource ## {#class-BaseUriSource} + + + + + + + + + + + + + + + + + +
Name:BaseUriSource
Summary: + Provides a base abstract for base Uri source + for Iri template resolution. +
Sub-class of:[=Resource=]
Named instances:[=Rfc3986=], [=LinkContext=]
+ +## hydra:Class ## {#class-Class} + + + + + + + + + + + + + +
Name:Class
Summary:The class of Hydra classes.
Sub-class of:`rdfs:Class`
+ +## hydra:Collection ## {#class-Collection} + + + + + + + + + + + + + +
Name:Collection
Summary: + A collection holding references to a number of related resources. +
Sub-class of:[=Resource=]
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api/posts", + "@type": "Collection", + "view": { + "@id": "http://api.example.com/api/posts?skip=10", + "@type": "PartialCollectionView", + "first": "http://api.example.com/api/posts", + "last": "http://api.example.com/api/posts?skip=100", + "previous": "http://api.example.com/api/posts", + "next": "http://api.example.com/api/posts?skip=20", + "totalItems": 10, + }, + "totalItems": 100, + "member": [ + { "@id": "http://api.example.com/api/posts/10" }, + { "@id": "http://api.example.com/api/posts/11" }, + { "@id": "http://api.example.com/api/posts/12" }, + { "@id": "http://api.example.com/api/posts/13" }, + { "@id": "http://api.example.com/api/posts/14" }, + { "@id": "http://api.example.com/api/posts/15" }, + { "@id": "http://api.example.com/api/posts/16" }, + { "@id": "http://api.example.com/api/posts/17" }, + { "@id": "http://api.example.com/api/posts/18" }, + { "@id": "http://api.example.com/api/posts/19" } + ], + "search": { + "template": "/api/posts{?search,limit,offset}", + "resolveRelativeUsing": "hydra:Rfc3986", + "mapping": [ + { + "variable": "search", + "property": "hydra:freetextQuery", + "required": true, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "limit", + "property": "hydra:limit", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "offset", + "property": "hydra:offset", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + } + ] + } +} + +
+ +## hydra:Error ## {#class-Error} + + + + + + + + + + + + + +
Name:Error
Summary: + A runtime error, used to report information beyond the returned + status code. +
Sub-class of:[=Status=]
+
+ +HTTP/1.1 400 Bad request +Content-Type: application/problem+json +Link: <http://www.w3.org/ns/hydra/error>; rel="http://www.w3.org/ns/json-ld#context" + +{ +"type": "https://api.example.com/vocab#NullReferenceException", +"@type": "http://www.w3.org/ns/hydra/core#Error", +"title": "The request cannot be processed.", +"detail": "Provided value cannot be 'null'.", +"instance": "http://api.example.com/api/posts", +"status": 404 +} + +
+ +## hydra:HeaderSpecification ## {#class-HeaderSpecification} + + + + + + + + + + + + + +
Name: + HeaderSpecification +
Summary:Specifies a possible either expected or returned header values.
Sub-class of:[=Resource=]
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api?documentation", + "@type": "ApiDocumentation", + "entrypoint": "http://api.example.com/api", + "extension": "https://w3id.org/hydra/extension#shacl", + "supportedClass": [ + { + "@id": "http://api.example.com/vocab#User", + "title": "User", + "description": "Describes a system user.", + "supportedOperation": [ + { + "method": "PUT", + "title": "Create new user", + "description": "Creates a brand new user.", + "expects": "http://api.example.com/vocab#User", + "returns": "http://api.example.com/vocab#User", + "returnsHeader": [ + { + "@type": "hydra:HeaderSpecification", + "headerName": "Content-Type", + "possibleValue": ["text/turtle", "application/ld+json"], + "closedSet": true + } + "Content-Length" + ], + "expectsHeader": [ + "Authorization", + { + "@type": "hydra:HeaderSpecification", + "headerName": "Content-Type", + "possibleValue": ["image/gif", "image/png"], + "closedSet": true + } + ] + } + ], + "supportedProperty": [ + { + "property": "http://api.example.com/vocab#login", + "writable": true, + "readable": true, + "required": true + } + ] + } + ] +} + +
+ +## hydra:IriTemplate ## {#class-IriTemplate} + + + + + + + + + +
Name:IriTemplate
Summary:The class of IRI templates.
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api/posts", + "@type": "Collection", + "view": { + "@id": "http://api.example.com/api/posts?skip=10", + "@type": "PartialCollectionView", + "first": "http://api.example.com/api/posts", + "last": "http://api.example.com/api/posts?skip=100", + "previous": "http://api.example.com/api/posts", + "next": "http://api.example.com/api/posts?skip=20", + "totalItems": 10, + }, + "totalItems": 100, + "member": [ + { "@id": "http://api.example.com/api/posts/10" }, + { "@id": "http://api.example.com/api/posts/11" }, + { "@id": "http://api.example.com/api/posts/12" }, + { "@id": "http://api.example.com/api/posts/13" }, + { "@id": "http://api.example.com/api/posts/14" }, + { "@id": "http://api.example.com/api/posts/15" }, + { "@id": "http://api.example.com/api/posts/16" }, + { "@id": "http://api.example.com/api/posts/17" }, + { "@id": "http://api.example.com/api/posts/18" }, + { "@id": "http://api.example.com/api/posts/19" } + ], + "search": { + "@type": "hydra:IriTemplate", + "template": "/api/posts{?search,limit,offset}", + "resolveRelativeUsing": "hydra:Rfc3986", + "mapping": [ + { + "variable": "search", + "property": "hydra:freetextQuery", + "required": true, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "limit", + "property": "hydra:limit", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "offset", + "property": "hydra:offset", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + } + ] + } +} + +
+ +## hydra:IriTemplateMapping ## {#class-IriTemplateMapping} + + + + + + + + + +
Name: + IriTemplateMapping +
Summary:A mapping from an IRI template variable to a property.
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api/posts", + "@type": "Collection", + "view": { + "@id": "http://api.example.com/api/posts?skip=10", + "@type": "PartialCollectionView", + "first": "http://api.example.com/api/posts", + "last": "http://api.example.com/api/posts?skip=100", + "previous": "http://api.example.com/api/posts", + "next": "http://api.example.com/api/posts?skip=20", + "totalItems": 10, + }, + "totalItems": 100, + "member": [ + { "@id": "http://api.example.com/api/posts/10" }, + { "@id": "http://api.example.com/api/posts/11" }, + { "@id": "http://api.example.com/api/posts/12" }, + { "@id": "http://api.example.com/api/posts/13" }, + { "@id": "http://api.example.com/api/posts/14" }, + { "@id": "http://api.example.com/api/posts/15" }, + { "@id": "http://api.example.com/api/posts/16" }, + { "@id": "http://api.example.com/api/posts/17" }, + { "@id": "http://api.example.com/api/posts/18" }, + { "@id": "http://api.example.com/api/posts/19" } + ], + "search": { + "@type": "hydra:IriTemplate", + "template": "/api/posts{?search,limit,offset}", + "resolveRelativeUsing": "hydra:Rfc3986", + "mapping": [ + { + "@type": "hydra:IriTemplateMapping", + "variable": "search", + "property": "hydra:freetextQuery", + "required": true, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "@type": "hydra:IriTemplateMapping", + "variable": "limit", + "property": "hydra:limit", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "@type": "hydra:IriTemplateMapping", + "variable": "offset", + "property": "hydra:offset", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + } + ] + } +} + +
+ +## hydra:Link ## {#class-Link} + + + + + + + + + + + + + +
Name:Link
Summary:The class of properties representing links.
Sub-class of:[=Resource=], `rdf:Property`
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@graph": [ + { + "@id": "http://api.example.com/api?documentation", + "@type": "ApiDocumentation", + "entrypoint": "http://api.example.com/api" + }, + { + "@id": "http://api.example.com/vocab#comments", + "@type": "hydra:Link" + } + } +} + +
+ +## hydra:Operation ## {#class-Operation} + + + + + + + + + +
Name:Operation
Summary:An operation.
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api/posts/1", + "operation": [ + { + "@type": "Operation", + "method": "DELETE", + "title": "Remove", + "description": "Removes post no. 1" + } + ] +} + +
+ +## hydra:PartialCollectionView ## {#class-PartialCollectionView} + + + + + + + + + + + + + +
Name: + + PartialCollectionView + +
Summary: + A PartialCollectionView describes a partial view of a Collection. + Multiple PartialCollectionViews can be connected with + the next/previous properties to allow a client to retrieve + all members of the collection. +
Sub-class of:[=Resource=]
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api/posts", + "@type": "Collection", + "view": { + "@type": "PartialCollectionView", + "@id": "http://api.example.com/api/posts?skip=10", + "@type": "PartialCollectionView", + "first": "http://api.example.com/api/posts", + "last": "http://api.example.com/api/posts?skip=100", + "previous": "http://api.example.com/api/posts", + "next": "http://api.example.com/api/posts?skip=20", + "totalItems": 10, + }, + "totalItems": 100, + "member": [ + { "@id": "http://api.example.com/api/posts/10" }, + { "@id": "http://api.example.com/api/posts/11" }, + { "@id": "http://api.example.com/api/posts/12" }, + { "@id": "http://api.example.com/api/posts/13" }, + { "@id": "http://api.example.com/api/posts/14" }, + { "@id": "http://api.example.com/api/posts/15" }, + { "@id": "http://api.example.com/api/posts/16" }, + { "@id": "http://api.example.com/api/posts/17" }, + { "@id": "http://api.example.com/api/posts/18" }, + { "@id": "http://api.example.com/api/posts/19" } + ], + "search": { + "template": "/api/posts{?search,limit,offset}", + "resolveRelativeUsing": "hydra:Rfc3986", + "mapping": [ + { + "variable": "search", + "property": "hydra:freetextQuery", + "required": true, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "limit", + "property": "hydra:limit", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "offset", + "property": "hydra:offset", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + } + ] + } +} + +
+ +## hydra:Resource ## {#class-Resource} + + + + + + + + + +
Name:Resource
Summary: + The class of dereferenceable resources by means a client + can attempt to dereference; however, the received responses + should still be verified. +
+ +## hydra:Status ## {#class-Status} + + + + + + + + + +
Name:Status
Summary: + Additional information about a status code that might be returned. +
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api/posts/1", + "operation": [ + { + "method": "DELETE", + "title": "Remove", + "description": "Removes post no. 1", + "possibleStatus": [ + { + "@type": "Status", + "statusCode": 303 + } + ] + } + ] +} + +
+ +## hydra:SupportedProperty ## {#class-SupportedProperty} + + + + + + + + + +
Name: + SupportedProperty +
Summary:A property known to be supported by a Hydra class.
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api?documentation", + "@type": "ApiDocumentation", + "entrypoint": "http://api.example.com/api", + "extension": "https://w3id.org/hydra/extension#shacl", + "supportedClass": [ + { + "@id": "http://api.example.com/vocab#User", + "title": "User", + "description": "Describes a system user.", + "supportedOperation": [ + { + "method": "PUT", + "title": "Create new user", + "description": "Creates a brand new user.", + "expects": "http://api.example.com/vocab#User", + "returns": "http://api.example.com/vocab#User", + "returnsHeader": [ + { + "headerName": "Content-Type", + "possibleValue": ["text/turtle", "application/ld+json"], + "closedSet": true + } + "Content-Length" + ], + "expectsHeader": [ + "Authorization", + { + "headerName": "Content-Type", + "possibleValue": ["image/gif", "image/png"], + "closedSet": true + } + ] + } + ], + "supportedProperty": [ + { + "@type": "SupportedProperty", + "property": "http://api.example.com/vocab#login", + "writable": true, + "readable": true, + "required": true + } + ] + } + ] +} + +
+ +## hydra:TemplatedLink ## {#class-TemplatedLink} + + + + + + + + + + + + + +
Name:TemplatedLink
Summary:A templated link.
Sub-class of:[=Resource=], `rdf:Property`
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@graph": [ + { + "@id": "http://api.example.com/api?documentation", + "@type": "ApiDocumentation", + "entrypoint": "http://api.example.com/api" + }, + { + "@id": "http://api.example.com/vocab#comments", + "@type": "hydra:TemplatedLink" + } + } +} + +
+ +## hydra:VariableRepresentation ## {#class-VariableRepresentation} + + + + + + + + + + + + + +
Name: + + VariableRepresentation + +
Summary: + A representation specifies how to serialize variable + values into strings. +
Named instances:[=BasicRepresentation=], [=ExplicitRepresentation=]
+ +Properties {#properties} +========== + +## hydra:apiDocumentation ## {#property-apiDocumentation} + + + + + + + + + + + + + + + + + +
Name:apiDocumentation‎
Summary:A link to the API documentation.
Domain:[=Resource=]
Range:[=ApiDocumentation=]
+
+ +HTTP/1.1 200 OK +Content-Type: text/html; charset=utf-8 +Link: <http://api.example.com/doc/>; rel="http://www.w3.org/ns/hydra/core#apiDocumentation" + +
+ +## hydra:closedSet ## {#property-closedSet} + + + + + + + + + + + + + + + + + + + + + +
Name:closedSet
Summary: + Determines whether the provided set of header values + is closed or not. +
Max cardinality:1
Domain:[=HeaderSpecification=]
Range:`xsd:boolean`
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api?documentation", + "@type": "ApiDocumentation", + "entrypoint": "http://api.example.com/api", + "extension": "https://w3id.org/hydra/extension#shacl", + "supportedClass": [ + { + "@id": "http://api.example.com/vocab#User", + "title": "User", + "description": "Describes a system user.", + "supportedOperation": [ + { + "method": "PUT", + "title": "Create new user", + "description": "Creates a brand new user.", + "expects": "http://api.example.com/vocab#User", + "returns": "http://api.example.com/vocab#User", + "returnsHeader": [ + { + "headerName": "Content-Type", + "possibleValue": ["text/turtle", "application/ld+json"], + "closedSet": true + } + "Content-Length" + ], + "expectsHeader": [ + "Authorization", + { + "headerName": "Content-Type", + "possibleValue": ["image/gif", "image/png"], + "closedSet": true + } + ] + } + ], + "supportedProperty": [ + { + "property": "http://api.example.com/vocab#login", + "writable": true, + "readable": true, + "required": true + } + ] + } + ] +} + +
+ +## hydra:collection ## {#property-collection} + + + + + + + + + + + + + +
Name:collection‎
Summary:Collections somehow related to this resource.
Range:[=Collection=]
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api", + "collection": [ + { + "@id": "http://api.example.com/api/posts", + "@type": "Collection", + "memberAssertion": [ + { + "property": "rdf:type", + "object": "http://api.example.com/vocab#Post" + } + ] + } + ] +} + +
+ +## hydra:description ## {#property-description} + + + + + + + + + + + + + + + + + + + + + +
Name:description
Summary:A description.
Max cardinality:1
Domain includes: + [=ApiDocumentation=], + [=Status=], + [=Class=], + [=SupportedProperty=], + [=Operation=], + [=Link=], + [=TemplatedLink=] +
Range:`xsd:string`
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api?documentation", + "@type": "ApiDocumentation", + "entrypoint": "http://api.example.com/api", + "extension": "https://w3id.org/hydra/extension#shacl", + "supportedClass": [ + { + "@id": "http://api.example.com/vocab#User", + "title": "User", + "description": "Describes a system user.", + "supportedOperation": [ + { + "method": "PUT", + "title": "Create new user", + "description": "Creates a brand new user.", + "expects": "http://api.example.com/vocab#User", + "returns": "http://api.example.com/vocab#User", + "returnsHeader": [ + { + "headerName": "Content-Type", + "possibleValue": ["text/turtle", "application/ld+json"], + "closedSet": true + } + "Content-Length" + ], + "expectsHeader": [ + "Authorization", + { + "headerName": "Content-Type", + "possibleValue": ["image/gif", "image/png"], + "closedSet": true + } + ] + } + ], + "supportedProperty": [ + { + "property": "http://api.example.com/vocab#login", + "writable": true, + "readable": true, + "required": true + } + ] + } + ] +} + +
+ +## hydra:entrypoint ## {#property-entrypoint} + + + + + + + + + + + + + + + + + + + + + +
Name:entrypoint
Summary:A link to main entry point of the Web API.
Min cardinality:1
Domain:[=ApiDocumentation=]
Range:[=Resource=]
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api?documentation", + "@type": "ApiDocumentation", + "entrypoint": "http://api.example.com/api", + "extension": "https://w3id.org/hydra/extension#shacl", + "supportedClass": [ + { + "@id": "http://api.example.com/vocab#User", + "title": "User", + "description": "Describes a system user.", + "supportedOperation": [ + { + "method": "PUT", + "title": "Create new user", + "description": "Creates a brand new user.", + "expects": "http://api.example.com/vocab#User", + "returns": "http://api.example.com/vocab#User", + "returnsHeader": [ + { + "headerName": "Content-Type", + "possibleValue": ["text/turtle", "application/ld+json"], + "closedSet": true + } + "Content-Length" + ], + "expectsHeader": [ + "Authorization", + { + "headerName": "Content-Type", + "possibleValue": ["image/gif", "image/png"], + "closedSet": true + } + ] + } + ], + "supportedProperty": [ + { + "property": "http://api.example.com/vocab#login", + "writable": true, + "readable": true, + "required": true + } + ] + } + ] +} + +
+ +## hydra:expects ## {#property-expects} + + + + + + + + + + + + + + + + + +
Name:expects
Summary:The information expected by the Web API.
Domain:[=Operation=]
Range includes: + `rdfs:Resource`, + [=Resource=], + `rdfs:Class`, + [=Class=] +
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api?documentation", + "@type": "ApiDocumentation", + "entrypoint": "http://api.example.com/api", + "extension": "https://w3id.org/hydra/extension#shacl", + "supportedClass": [ + { + "@id": "http://api.example.com/vocab#User", + "title": "User", + "description": "Describes a system user.", + "supportedOperation": [ + { + "method": "PUT", + "title": "Create new user", + "description": "Creates a brand new user.", + "expects": "http://api.example.com/vocab#User", + "returns": "http://api.example.com/vocab#User", + "returnsHeader": [ + { + "headerName": "Content-Type", + "possibleValue": ["text/turtle", "application/ld+json"], + "closedSet": true + } + "Content-Length" + ], + "expectsHeader": [ + "Authorization", + { + "headerName": "Content-Type", + "possibleValue": ["image/gif", "image/png"], + "closedSet": true + } + ] + } + ], + "supportedProperty": [ + { + "property": "http://api.example.com/vocab#login", + "writable": true, + "readable": true, + "required": true + } + ] + } + ] +} + +
+ +## hydra:expectsHeader ## {#property-expectsHeader} + + + + + + + + + + + + + + + + + +
Name:expectsHeader
Summary:Specification of the header expected by the operation.
Domain:[=Operation=]
Range includes: + `xsd:string`, + [=HeaderSpecification=] +
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api?documentation", + "@type": "ApiDocumentation", + "entrypoint": "http://api.example.com/api", + "extension": "https://w3id.org/hydra/extension#shacl", + "supportedClass": [ + { + "@id": "http://api.example.com/vocab#User", + "title": "User", + "description": "Describes a system user.", + "supportedOperation": [ + { + "method": "PUT", + "title": "Create new user", + "description": "Creates a brand new user.", + "expects": "http://api.example.com/vocab#User", + "returns": "http://api.example.com/vocab#User", + "returnsHeader": [ + { + "headerName": "Content-Type", + "possibleValue": ["text/turtle", "application/ld+json"], + "closedSet": true + } + "Content-Length" + ], + "expectsHeader": [ + "Authorization", + { + "headerName": "Content-Type", + "possibleValue": ["image/gif", "image/png"], + "closedSet": true + } + ] + } + ], + "supportedProperty": [ + { + "property": "http://api.example.com/vocab#login", + "writable": true, + "readable": true, + "required": true + } + ] + } + ] +} + +
+ +## hydra:extension ## {#property-extension} + + + + + + + + + + + + + +
Name:extension
Summary:Hint on what kind of extensions are in use.
Domain:[=ApiDocumentation=]
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api?documentation", + "@type": "ApiDocumentation", + "entrypoint": "http://api.example.com/api", + "extension": "https://w3id.org/hydra/extension#shacl", + "supportedClass": [ + { + "@id": "http://api.example.com/vocab#User", + "title": "User", + "description": "Describes a system user.", + "supportedOperation": [ + { + "method": "PUT", + "title": "Create new user", + "description": "Creates a brand new user.", + "expects": "http://api.example.com/vocab#User", + "returns": "http://api.example.com/vocab#User", + "returnsHeader": [ + { + "headerName": "Content-Type", + "possibleValue": ["text/turtle", "application/ld+json"], + "closedSet": true + } + "Content-Length" + ], + "expectsHeader": [ + "Authorization", + { + "headerName": "Content-Type", + "possibleValue": ["image/gif", "image/png"], + "closedSet": true + } + ] + } + ], + "supportedProperty": [ + { + "property": "http://api.example.com/vocab#login", + "writable": true, + "readable": true, + "required": true + } + ] + } + ] +} + +
+ +## hydra:first ## {#property-first} + + + + + + + + + + + + + + + + + + + + + +
Name:first
Summary:The first resource of an interlinked set of resources.
Max cardinality:1
Domain:[=Resource=]
Range:[=Resource=]
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api/posts", + "@type": "Collection", + "view": { + "@id": "http://api.example.com/api/posts?skip=10", + "@type": "PartialCollectionView", + "first": "http://api.example.com/api/posts", + "last": "http://api.example.com/api/posts?skip=100", + "previous": "http://api.example.com/api/posts", + "next": "http://api.example.com/api/posts?skip=20", + "totalItems": 10, + }, + "totalItems": 100, + "member": [ + { "@id": "http://api.example.com/api/posts/10" }, + { "@id": "http://api.example.com/api/posts/11" }, + { "@id": "http://api.example.com/api/posts/12" }, + { "@id": "http://api.example.com/api/posts/13" }, + { "@id": "http://api.example.com/api/posts/14" }, + { "@id": "http://api.example.com/api/posts/15" }, + { "@id": "http://api.example.com/api/posts/16" }, + { "@id": "http://api.example.com/api/posts/17" }, + { "@id": "http://api.example.com/api/posts/18" }, + { "@id": "http://api.example.com/api/posts/19" } + ], + "search": { + "template": "/api/posts{?search,limit,offset}", + "resolveRelativeUsing": "hydra:Rfc3986", + "mapping": [ + { + "variable": "search", + "property": "hydra:freetextQuery", + "required": true, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "limit", + "property": "hydra:limit", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "offset", + "property": "hydra:offset", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + } + ] + } +} + +
+ +## hydra:freetextQuery ## {#property-freetextQuery} + + + + + + + + + + + + + + + + + +
Name:freetextQuery
Summary:A property representing a freetext query.
Domain:[=Resource=]
Range:`xsd:string`
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api/posts", + "@type": "Collection", + "view": { + "@id": "http://api.example.com/api/posts?skip=10", + "@type": "PartialCollectionView", + "first": "http://api.example.com/api/posts", + "last": "http://api.example.com/api/posts?skip=100", + "previous": "http://api.example.com/api/posts", + "next": "http://api.example.com/api/posts?skip=20", + "totalItems": 10, + }, + "totalItems": 100, + "member": [ + { "@id": "http://api.example.com/api/posts/10" }, + { "@id": "http://api.example.com/api/posts/11" }, + { "@id": "http://api.example.com/api/posts/12" }, + { "@id": "http://api.example.com/api/posts/13" }, + { "@id": "http://api.example.com/api/posts/14" }, + { "@id": "http://api.example.com/api/posts/15" }, + { "@id": "http://api.example.com/api/posts/16" }, + { "@id": "http://api.example.com/api/posts/17" }, + { "@id": "http://api.example.com/api/posts/18" }, + { "@id": "http://api.example.com/api/posts/19" } + ], + "search": { + "template": "/api/posts{?search,limit,offset}", + "resolveRelativeUsing": "hydra:Rfc3986", + "mapping": [ + { + "variable": "search", + "property": "hydra:freetextQuery", + "required": true, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "limit", + "property": "hydra:limit", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "offset", + "property": "hydra:offset", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + } + ] + } +} + +
+ +## hydra:headerName ## {#property-headerName} + + + + + + + + + + + + + + + + + + + + + + + + + +
Name:headerName
Summary:Name of the header.
Min cardinality:1
Max cardinality:1
Domain:[=HeaderSpecification=]
Range:`xsd:string`
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api?documentation", + "@type": "ApiDocumentation", + "entrypoint": "http://api.example.com/api", + "extension": "https://w3id.org/hydra/extension#shacl", + "supportedClass": [ + { + "@id": "http://api.example.com/vocab#User", + "title": "User", + "description": "Describes a system user.", + "supportedOperation": [ + { + "method": "PUT", + "title": "Create new user", + "description": "Creates a brand new user.", + "expects": "http://api.example.com/vocab#User", + "returns": "http://api.example.com/vocab#User", + "returnsHeader": [ + { + "headerName": "Content-Type", + "possibleValue": ["text/turtle", "application/ld+json"], + "closedSet": true + } + "Content-Length" + ], + "expectsHeader": [ + "Authorization", + { + "headerName": "Content-Type", + "possibleValue": ["image/gif", "image/png"], + "closedSet": true + } + ] + } + ], + "supportedProperty": [ + { + "property": "http://api.example.com/vocab#login", + "writable": true, + "readable": true, + "required": true + } + ] + } + ] +} + +
+ +## hydra:last ## {#property-last} + + + + + + + + + + + + + + + + + + + + + +
Name:last
Summary:The last resource of an interlinked set of resources.
Max cardinality:1
Domain:[=Resource=]
Range:[=Resource=]
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api/posts", + "@type": "Collection", + "view": { + "@id": "http://api.example.com/api/posts?skip=10", + "@type": "PartialCollectionView", + "first": "http://api.example.com/api/posts", + "last": "http://api.example.com/api/posts?skip=100", + "previous": "http://api.example.com/api/posts", + "next": "http://api.example.com/api/posts?skip=20", + "totalItems": 10, + }, + "totalItems": 100, + "member": [ + { "@id": "http://api.example.com/api/posts/10" }, + { "@id": "http://api.example.com/api/posts/11" }, + { "@id": "http://api.example.com/api/posts/12" }, + { "@id": "http://api.example.com/api/posts/13" }, + { "@id": "http://api.example.com/api/posts/14" }, + { "@id": "http://api.example.com/api/posts/15" }, + { "@id": "http://api.example.com/api/posts/16" }, + { "@id": "http://api.example.com/api/posts/17" }, + { "@id": "http://api.example.com/api/posts/18" }, + { "@id": "http://api.example.com/api/posts/19" } + ], + "search": { + "template": "/api/posts{?search,limit,offset}", + "resolveRelativeUsing": "hydra:Rfc3986", + "mapping": [ + { + "variable": "search", + "property": "hydra:freetextQuery", + "required": true, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "limit", + "property": "hydra:limit", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "offset", + "property": "hydra:offset", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + } + ] + } +} + +
+ +## hydra:limit ## {#property-limit} + + + + + + + + + + + + + + + + + +
Name:limit
Summary:Instructs to limit set only to N elements.
Max cardinality:1
Range:`xsd:nonNegativeInteger`
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api/posts", + "@type": "Collection", + "view": { + "@id": "http://api.example.com/api/posts?skip=10", + "@type": "PartialCollectionView", + "first": "http://api.example.com/api/posts", + "last": "http://api.example.com/api/posts?skip=100", + "previous": "http://api.example.com/api/posts", + "next": "http://api.example.com/api/posts?skip=20", + "totalItems": 10, + }, + "totalItems": 100, + "member": [ + { "@id": "http://api.example.com/api/posts/10" }, + { "@id": "http://api.example.com/api/posts/11" }, + { "@id": "http://api.example.com/api/posts/12" }, + { "@id": "http://api.example.com/api/posts/13" }, + { "@id": "http://api.example.com/api/posts/14" }, + { "@id": "http://api.example.com/api/posts/15" }, + { "@id": "http://api.example.com/api/posts/16" }, + { "@id": "http://api.example.com/api/posts/17" }, + { "@id": "http://api.example.com/api/posts/18" }, + { "@id": "http://api.example.com/api/posts/19" } + ], + "search": { + "template": "/api/posts{?search,limit,offset}", + "resolveRelativeUsing": "hydra:Rfc3986", + "mapping": [ + { + "variable": "search", + "property": "hydra:freetextQuery", + "required": true, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "limit", + "property": "hydra:limit", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "offset", + "property": "hydra:offset", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + } + ] + } +} + +
+ +## hydra:mapping ## {#property-mapping} + + + + + + + + + + + + + + + + + + + + + +
Name:mapping
Summary:A variable-to-property mapping of the IRI template.
Min cardinality:1
Domain:[=IriTemplate=]
Range:[=IriTemplateMapping=]
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api/posts", + "@type": "Collection", + "view": { + "@id": "http://api.example.com/api/posts?skip=10", + "@type": "PartialCollectionView", + "first": "http://api.example.com/api/posts", + "last": "http://api.example.com/api/posts?skip=100", + "previous": "http://api.example.com/api/posts", + "next": "http://api.example.com/api/posts?skip=20", + "totalItems": 10, + }, + "totalItems": 100, + "member": [ + { "@id": "http://api.example.com/api/posts/10" }, + { "@id": "http://api.example.com/api/posts/11" }, + { "@id": "http://api.example.com/api/posts/12" }, + { "@id": "http://api.example.com/api/posts/13" }, + { "@id": "http://api.example.com/api/posts/14" }, + { "@id": "http://api.example.com/api/posts/15" }, + { "@id": "http://api.example.com/api/posts/16" }, + { "@id": "http://api.example.com/api/posts/17" }, + { "@id": "http://api.example.com/api/posts/18" }, + { "@id": "http://api.example.com/api/posts/19" } + ], + "search": { + "template": "/api/posts{?search,limit,offset}", + "resolveRelativeUsing": "hydra:Rfc3986", + "mapping": [ + { + "variable": "search", + "property": "hydra:freetextQuery", + "required": true, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "limit", + "property": "hydra:limit", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "offset", + "property": "hydra:offset", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + } + ] + } +} + +
+ +## hydra:member ## {#property-member} + + + + + + + + + + + + + +
Name:member
Summary:A member of the collection.
Domain:[=Collection=]
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api/posts", + "@type": "Collection", + "view": { + "@id": "http://api.example.com/api/posts?skip=10", + "@type": "PartialCollectionView", + "first": "http://api.example.com/api/posts", + "last": "http://api.example.com/api/posts?skip=100", + "previous": "http://api.example.com/api/posts", + "next": "http://api.example.com/api/posts?skip=20", + "totalItems": 10, + }, + "totalItems": 100, + "member": [ + { "@id": "http://api.example.com/api/posts/10" }, + { "@id": "http://api.example.com/api/posts/11" }, + { "@id": "http://api.example.com/api/posts/12" }, + { "@id": "http://api.example.com/api/posts/13" }, + { "@id": "http://api.example.com/api/posts/14" }, + { "@id": "http://api.example.com/api/posts/15" }, + { "@id": "http://api.example.com/api/posts/16" }, + { "@id": "http://api.example.com/api/posts/17" }, + { "@id": "http://api.example.com/api/posts/18" }, + { "@id": "http://api.example.com/api/posts/19" } + ], + "search": { + "template": "/api/posts{?search,limit,offset}", + "resolveRelativeUsing": "hydra:Rfc3986", + "mapping": [ + { + "variable": "search", + "property": "hydra:freetextQuery", + "required": true, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "limit", + "property": "hydra:limit", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "offset", + "property": "hydra:offset", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + } + ] + } +} + +
+ +## hydra:memberAssertion ## {#property-memberAssertion} + + + + + + + + + + + + + + + + + +
Name:memberAssertion
Summary:Semantics of each member provided by the collection.
Domain includes:[=Collection=], [=Class=]
Range:
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api", + "collection": [ + { + "@id": "http://api.example.com/api/posts", + "@type": "Collection", + "memberAssertion": [ + { + "property": "rdf:type", + "object": "http://api.example.com/vocab#Post" + } + ] + } + ] +} + +
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api/posts/1/comments", + "@type": "Collection", + "memberAssertion": [ + { + "subject": "http://api.example.com/api/posts/1", + "property": "http://api.example.com/vocab#comment" + } + ] +} + +
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@graph": [ + { + "@id": "http://api.example.com/api?documentation", + "@type": "ApiDocumentation", + "entrypoint": "http://api.example.com/api" + }, + { + "@id": "http://api.example.com/vocab#comments", + "@type": "hydra:Link", + "supportedOperation": [ + { + "method": "GET", + "returns": { + "subClassOf": "hydra:Collection", + "memberAssertion": { + "property": "rdf:type", + "object": "http://api.example.com/vocab#Comment" + } + } + } + ] + } + } +} + +
+ +## hydra:method ## {#property-method} + + + + + + + + + + + + + + + + + +
Name:method
Summary:The protocol method.
Domain:[=Operation=]
Range:`xsd:string`
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api?documentation", + "@type": "ApiDocumentation", + "entrypoint": "http://api.example.com/api", + "extension": "https://w3id.org/hydra/extension#shacl", + "supportedClass": [ + { + "@id": "http://api.example.com/vocab#User", + "title": "User", + "description": "Describes a system user.", + "supportedOperation": [ + { + "method": "PUT", + "title": "Create new user", + "description": "Creates a brand new user.", + "expects": "http://api.example.com/vocab#User", + "returns": "http://api.example.com/vocab#User", + "returnsHeader": [ + { + "headerName": "Content-Type", + "possibleValue": ["text/turtle", "application/ld+json"], + "closedSet": true + } + "Content-Length" + ], + "expectsHeader": [ + "Authorization", + { + "headerName": "Content-Type", + "possibleValue": ["image/gif", "image/png"], + "closedSet": true + } + ] + } + ], + "supportedProperty": [ + { + "property": "http://api.example.com/vocab#login", + "writable": true, + "readable": true, + "required": true + } + ] + } + ] +} + +
+ +## hydra:next ## {#property-next} + + + + + + + + + + + + + + + + + + + + + +
Name:next
Summary: + The resource following the current instance + in an interlinked set of resources. +
Max cardinality:1
Domain:[=Resource=]
Range:[=Resource=]
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api/posts", + "@type": "Collection", + "view": { + "@id": "http://api.example.com/api/posts?skip=10", + "@type": "PartialCollectionView", + "first": "http://api.example.com/api/posts", + "last": "http://api.example.com/api/posts?skip=100", + "previous": "http://api.example.com/api/posts", + "next": "http://api.example.com/api/posts?skip=20", + "totalItems": 10, + }, + "totalItems": 100, + "member": [ + { "@id": "http://api.example.com/api/posts/10" }, + { "@id": "http://api.example.com/api/posts/11" }, + { "@id": "http://api.example.com/api/posts/12" }, + { "@id": "http://api.example.com/api/posts/13" }, + { "@id": "http://api.example.com/api/posts/14" }, + { "@id": "http://api.example.com/api/posts/15" }, + { "@id": "http://api.example.com/api/posts/16" }, + { "@id": "http://api.example.com/api/posts/17" }, + { "@id": "http://api.example.com/api/posts/18" }, + { "@id": "http://api.example.com/api/posts/19" } + ], + "search": { + "template": "/api/posts{?search,limit,offset}", + "resolveRelativeUsing": "hydra:Rfc3986", + "mapping": [ + { + "variable": "search", + "property": "hydra:freetextQuery", + "required": true, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "limit", + "property": "hydra:limit", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "offset", + "property": "hydra:offset", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + } + ] + } +} + +
+ +## hydra:object ## {#property-object} + + + + + + + + + + + + + +
Name:object
Summary:The object.
Min cardinality:1
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api", + "collection": [ + { + "@id": "http://api.example.com/api/posts", + "@type": "Collection", + "memberAssertion": [ + { + "property": "rdf:type", + "object": "http://api.example.com/vocab#Post" + } + ] + } + ] +} + +
+ +## hydra:offset ## {#property-offset} + + + + + + + + + + + + + + + + + +
Name:offset
Summary:Instructs to skip N elements of the set.
Max cardinality:1
Range:`xsd:nonNegativeInteger`
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api/posts", + "@type": "Collection", + "view": { + "@id": "http://api.example.com/api/posts?skip=10", + "@type": "PartialCollectionView", + "first": "http://api.example.com/api/posts", + "last": "http://api.example.com/api/posts?skip=100", + "previous": "http://api.example.com/api/posts", + "next": "http://api.example.com/api/posts?skip=20", + "totalItems": 10, + }, + "totalItems": 100, + "member": [ + { "@id": "http://api.example.com/api/posts/10" }, + { "@id": "http://api.example.com/api/posts/11" }, + { "@id": "http://api.example.com/api/posts/12" }, + { "@id": "http://api.example.com/api/posts/13" }, + { "@id": "http://api.example.com/api/posts/14" }, + { "@id": "http://api.example.com/api/posts/15" }, + { "@id": "http://api.example.com/api/posts/16" }, + { "@id": "http://api.example.com/api/posts/17" }, + { "@id": "http://api.example.com/api/posts/18" }, + { "@id": "http://api.example.com/api/posts/19" } + ], + "search": { + "template": "/api/posts{?search,limit,offset}", + "resolveRelativeUsing": "hydra:Rfc3986", + "mapping": [ + { + "variable": "search", + "property": "hydra:freetextQuery", + "required": true, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "limit", + "property": "hydra:limit", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "offset", + "property": "hydra:offset", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + } + ] + } +} + +
+ +## hydra:operation ## {#property-operation} + + + + + + + + + + + + + + + + + +
Name:operation‎
Summary:An operation supported by the Hydra resource.
Domain:[=Resource=]
Range:[=Operation=]
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api/posts/1", + "operation": [ + { + "method": "DELETE", + "title": "Remove", + "description": "Removes post no. 1" + } + ] +} + +
+ +## hydra:pageIndex ## {#property-pageIndex} + + + + + + + + + + + + + + + + + +
Name:pageIndex
Summary: + Instructs to provide a specific page of the collection + at a given index. +
Max cardinality:1
Range:`xsd:nonNegativeInteger`
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api/posts", + "@type": "Collection", + "view": { + "@id": "http://api.example.com/api/posts?skip=10", + "@type": "PartialCollectionView", + "first": "http://api.example.com/api/posts", + "last": "http://api.example.com/api/posts?skip=100", + "previous": "http://api.example.com/api/posts", + "next": "http://api.example.com/api/posts?skip=20", + "totalItems": 10, + }, + "totalItems": 100, + "member": [ + { "@id": "http://api.example.com/api/posts/10" }, + { "@id": "http://api.example.com/api/posts/11" }, + { "@id": "http://api.example.com/api/posts/12" }, + { "@id": "http://api.example.com/api/posts/13" }, + { "@id": "http://api.example.com/api/posts/14" }, + { "@id": "http://api.example.com/api/posts/15" }, + { "@id": "http://api.example.com/api/posts/16" }, + { "@id": "http://api.example.com/api/posts/17" }, + { "@id": "http://api.example.com/api/posts/18" }, + { "@id": "http://api.example.com/api/posts/19" } + ], + "search": { + "template": "/api/posts{?search,page,limit}", + "resolveRelativeUsing": "hydra:Rfc3986", + "mapping": [ + { + "variable": "search", + "property": "hydra:freetextQuery", + "required": true, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "limit", + "property": "hydra:limit", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "page", + "property": "hydra:pageIndex", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + } + ] + } +} + +
+ +## hydra:pageReference ## {#property-pageReference} + + + + + + + + + + + + + +
Name:pageReference
Summary: + Instructs to provide a specific page reference + of the collection. +
Max cardinality:1
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api/posts", + "@type": "Collection", + "view": { + "@id": "http://api.example.com/api/posts?skip=10", + "@type": "PartialCollectionView", + "first": "http://api.example.com/api/posts", + "last": "http://api.example.com/api/posts?skip=100", + "previous": "http://api.example.com/api/posts", + "next": "http://api.example.com/api/posts?skip=20", + "totalItems": 10, + }, + "totalItems": 100, + "member": [ + { "@id": "http://api.example.com/api/posts/10" }, + { "@id": "http://api.example.com/api/posts/11" }, + { "@id": "http://api.example.com/api/posts/12" }, + { "@id": "http://api.example.com/api/posts/13" }, + { "@id": "http://api.example.com/api/posts/14" }, + { "@id": "http://api.example.com/api/posts/15" }, + { "@id": "http://api.example.com/api/posts/16" }, + { "@id": "http://api.example.com/api/posts/17" }, + { "@id": "http://api.example.com/api/posts/18" }, + { "@id": "http://api.example.com/api/posts/19" } + ], + "search": { + "template": "/api/posts{?search,partOfDay,limit}", + "resolveRelativeUsing": "hydra:Rfc3986", + "mapping": [ + { + "variable": "search", + "property": "hydra:freetextQuery", + "required": true, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "limit", + "property": "hydra:limit", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "partOfDay", + "property": "hydra:pageReference", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + } + ] + } +} + +
+ +## hydra:possibleStatus ## {#property-possibleStatus} + + + + + + + + + + + + + + + + + +
Name:possibleStatus
Summary: + A status that might be returned by the Web API (other + statuses should be expected and properly handled as well). +
Domain includes:[=ApiDocumentation=], [=Operation=]
Range:[=Status=]
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api/posts/1", + "operation": [ + { + "method": "DELETE", + "title": "Remove", + "description": "Removes post no. 1", + "possibleStatus": [ + { + "@type": "Status", + "statusCode": 303 + } + ] + } + ] +} + +
+ +## hydra:possibleValue ## {#property-possibleValue} + + + + + + + + + + + + + + + + + + + + + +
Name:possibleValue
Summary:Possible value of the header.
Min cardinality:1
Domain:[=HeaderSpecification=]
Range:`xsd:string`
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api?documentation", + "@type": "ApiDocumentation", + "entrypoint": "http://api.example.com/api", + "extension": "https://w3id.org/hydra/extension#shacl", + "supportedClass": [ + { + "@id": "http://api.example.com/vocab#User", + "title": "User", + "description": "Describes a system user.", + "supportedOperation": [ + { + "method": "PUT", + "title": "Create new user", + "description": "Creates a brand new user.", + "expects": "http://api.example.com/vocab#User", + "returns": "http://api.example.com/vocab#User", + "returnsHeader": [ + { + "headerName": "Content-Type", + "possibleValue": ["text/turtle", "application/ld+json"], + "closedSet": true + } + "Content-Length" + ], + "expectsHeader": [ + "Authorization", + { + "headerName": "Content-Type", + "possibleValue": ["image/gif", "image/png"], + "closedSet": true + } + ] + } + ], + "supportedProperty": [ + { + "property": "http://api.example.com/vocab#login", + "writable": true, + "readable": true, + "required": true + } + ] + } + ] +} + +
+ +## hydra:previous ## {#property-previous} + + + + + + + + + + + + + + + + + + + + + +
Name:previous
Summary: + The resource preceding the current instance + in an interlinked set of resources. +
Max cardinality:1
Domain:[=Resource=]
Range:[=Resource=]
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api/posts", + "@type": "Collection", + "view": { + "@id": "http://api.example.com/api/posts?skip=10", + "@type": "PartialCollectionView", + "first": "http://api.example.com/api/posts", + "last": "http://api.example.com/api/posts?skip=100", + "previous": "http://api.example.com/api/posts", + "next": "http://api.example.com/api/posts?skip=20", + "totalItems": 10, + }, + "totalItems": 100, + "member": [ + { "@id": "http://api.example.com/api/posts/10" }, + { "@id": "http://api.example.com/api/posts/11" }, + { "@id": "http://api.example.com/api/posts/12" }, + { "@id": "http://api.example.com/api/posts/13" }, + { "@id": "http://api.example.com/api/posts/14" }, + { "@id": "http://api.example.com/api/posts/15" }, + { "@id": "http://api.example.com/api/posts/16" }, + { "@id": "http://api.example.com/api/posts/17" }, + { "@id": "http://api.example.com/api/posts/18" }, + { "@id": "http://api.example.com/api/posts/19" } + ], + "search": { + "template": "/api/posts{?search,limit,offset}", + "resolveRelativeUsing": "hydra:Rfc3986", + "mapping": [ + { + "variable": "search", + "property": "hydra:freetextQuery", + "required": true, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "limit", + "property": "hydra:limit", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "offset", + "property": "hydra:offset", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + } + ] + } +} + +
+ +## hydra:property ## {#property-property} + + + + + + + + + + + + (only when used in context of [=memberAssertion=]) + + + + + + + + + +
Name:property
Summary:A property.
Min cardinality:1
Domain includes:[=SupportedProperty=], [=IriTemplateMapping=]
Range:`rdf:Property`
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api?documentation", + "@type": "ApiDocumentation", + "entrypoint": "http://api.example.com/api", + "extension": "https://w3id.org/hydra/extension#shacl", + "supportedClass": [ + { + "@id": "http://api.example.com/vocab#User", + "title": "User", + "description": "Describes a system user.", + "supportedOperation": [ + { + "method": "PUT", + "title": "Create new user", + "description": "Creates a brand new user.", + "expects": "http://api.example.com/vocab#User", + "returns": "http://api.example.com/vocab#User", + "returnsHeader": [ + { + "headerName": "Content-Type", + "possibleValue": ["text/turtle", "application/ld+json"], + "closedSet": true + } + "Content-Length" + ], + "expectsHeader": [ + "Authorization", + { + "headerName": "Content-Type", + "possibleValue": ["image/gif", "image/png"], + "closedSet": true + } + ] + } + ], + "supportedProperty": [ + { + "property": "http://api.example.com/vocab#login", + "writable": true, + "readable": true, + "required": true + } + ] + } + ] +} + +
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api/posts", + "@type": "Collection", + "view": { + "@id": "http://api.example.com/api/posts?skip=10", + "@type": "PartialCollectionView", + "first": "http://api.example.com/api/posts", + "last": "http://api.example.com/api/posts?skip=100", + "previous": "http://api.example.com/api/posts", + "next": "http://api.example.com/api/posts?skip=20", + "totalItems": 10, + }, + "totalItems": 100, + "member": [ + { "@id": "http://api.example.com/api/posts/10" }, + { "@id": "http://api.example.com/api/posts/11" }, + { "@id": "http://api.example.com/api/posts/12" }, + { "@id": "http://api.example.com/api/posts/13" }, + { "@id": "http://api.example.com/api/posts/14" }, + { "@id": "http://api.example.com/api/posts/15" }, + { "@id": "http://api.example.com/api/posts/16" }, + { "@id": "http://api.example.com/api/posts/17" }, + { "@id": "http://api.example.com/api/posts/18" }, + { "@id": "http://api.example.com/api/posts/19" } + ], + "search": { + "template": "/api/posts{?search,limit,offset}", + "resolveRelativeUsing": "hydra:Rfc3986", + "mapping": [ + { + "variable": "search", + "property": "hydra:freetextQuery", + "required": true, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "limit", + "property": "hydra:limit", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "offset", + "property": "hydra:offset", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + } + ] + } +} + +
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api", + "collection": [ + { + "@id": "http://api.example.com/api/posts", + "@type": "Collection", + "memberAssertion": [ + { + "property": "rdf:type", + "object": "http://api.example.com/vocab#Post" + } + ] + } + ] +} + +
+ +## hydra:readable ## {#property-readable} + + + + + + + + + + + + + + + + + + + + + +
Name:readable
Summary: + True if the client can retrieve the property's value, + false otherwise. +
Max cardinality:1
Domain:[=SupportedProperty=]
Range:`xsd:boolean`
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api?documentation", + "@type": "ApiDocumentation", + "entrypoint": "http://api.example.com/api", + "extension": "https://w3id.org/hydra/extension#shacl", + "supportedClass": [ + { + "@id": "http://api.example.com/vocab#User", + "title": "User", + "description": "Describes a system user.", + "supportedOperation": [ + { + "method": "PUT", + "title": "Create new user", + "description": "Creates a brand new user.", + "expects": "http://api.example.com/vocab#User", + "returns": "http://api.example.com/vocab#User", + "returnsHeader": [ + { + "headerName": "Content-Type", + "possibleValue": ["text/turtle", "application/ld+json"], + "closedSet": true + } + "Content-Length" + ], + "expectsHeader": [ + "Authorization", + { + "headerName": "Content-Type", + "possibleValue": ["image/gif", "image/png"], + "closedSet": true + } + ] + } + ], + "supportedProperty": [ + { + "property": "http://api.example.com/vocab#login", + "writable": true, + "readable": true, + "required": true + } + ] + } + ] +} + +
+ +## hydra:required ## {#property-required} + + + + + + + + + + + + + + + + + + + + + +
Name:required
Summary:True if the property is required, false otherwise.
Max cardinality:1
Domain includes:[=SupportedProperty=], [=IriTemplateMapping=]
Range:`xsd:boolean`
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api?documentation", + "@type": "ApiDocumentation", + "entrypoint": "http://api.example.com/api", + "extension": "https://w3id.org/hydra/extension#shacl", + "supportedClass": [ + { + "@id": "http://api.example.com/vocab#User", + "title": "User", + "description": "Describes a system user.", + "supportedOperation": [ + { + "method": "PUT", + "title": "Create new user", + "description": "Creates a brand new user.", + "expects": "http://api.example.com/vocab#User", + "returns": "http://api.example.com/vocab#User", + "returnsHeader": [ + { + "headerName": "Content-Type", + "possibleValue": ["text/turtle", "application/ld+json"], + "closedSet": true + } + "Content-Length" + ], + "expectsHeader": [ + "Authorization", + { + "headerName": "Content-Type", + "possibleValue": ["image/gif", "image/png"], + "closedSet": true + } + ] + } + ], + "supportedProperty": [ + { + "property": "http://api.example.com/vocab#login", + "writable": true, + "readable": true, + "required": true + } + ] + } + ] +} + +
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api/posts", + "@type": "Collection", + "view": { + "@id": "http://api.example.com/api/posts?skip=10", + "@type": "PartialCollectionView", + "first": "http://api.example.com/api/posts", + "last": "http://api.example.com/api/posts?skip=100", + "previous": "http://api.example.com/api/posts", + "next": "http://api.example.com/api/posts?skip=20", + "totalItems": 10, + }, + "totalItems": 100, + "member": [ + { "@id": "http://api.example.com/api/posts/10" }, + { "@id": "http://api.example.com/api/posts/11" }, + { "@id": "http://api.example.com/api/posts/12" }, + { "@id": "http://api.example.com/api/posts/13" }, + { "@id": "http://api.example.com/api/posts/14" }, + { "@id": "http://api.example.com/api/posts/15" }, + { "@id": "http://api.example.com/api/posts/16" }, + { "@id": "http://api.example.com/api/posts/17" }, + { "@id": "http://api.example.com/api/posts/18" }, + { "@id": "http://api.example.com/api/posts/19" } + ], + "search": { + "template": "/api/posts{?search,limit,offset}", + "resolveRelativeUsing": "hydra:Rfc3986", + "mapping": [ + { + "variable": "search", + "property": "hydra:freetextQuery", + "required": true, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "limit", + "property": "hydra:limit", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "offset", + "property": "hydra:offset", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + } + ] + } +} + +
+ +## hydra:resolveRelativeUsing ## {#property-resolveRelativeUsing} + + + + + + + + + + + + + +
Name:resolveRelativeUsing
Summary: + Instructs on how to resolve relative Uri created + by the Iri template resolution. +
Max cardinality:1
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api/posts", + "@type": "Collection", + "view": { + "@id": "http://api.example.com/api/posts?skip=10", + "@type": "PartialCollectionView", + "first": "http://api.example.com/api/posts", + "last": "http://api.example.com/api/posts?skip=100", + "previous": "http://api.example.com/api/posts", + "next": "http://api.example.com/api/posts?skip=20", + "totalItems": 10, + }, + "totalItems": 100, + "member": [ + { "@id": "http://api.example.com/api/posts/10" }, + { "@id": "http://api.example.com/api/posts/11" }, + { "@id": "http://api.example.com/api/posts/12" }, + { "@id": "http://api.example.com/api/posts/13" }, + { "@id": "http://api.example.com/api/posts/14" }, + { "@id": "http://api.example.com/api/posts/15" }, + { "@id": "http://api.example.com/api/posts/16" }, + { "@id": "http://api.example.com/api/posts/17" }, + { "@id": "http://api.example.com/api/posts/18" }, + { "@id": "http://api.example.com/api/posts/19" } + ], + "search": { + "template": "/api/posts{?search,limit,offset}", + "resolveRelativeUsing": "hydra:Rfc3986", + "mapping": [ + { + "variable": "search", + "property": "hydra:freetextQuery", + "required": true, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "limit", + "property": "hydra:limit", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "offset", + "property": "hydra:offset", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + } + ] + } +} + +
+ +## hydra:returns ## {#property-returns} + + + + + + + + + + + + + + + + + +
Name:returns
Summary:The information returned by the Web API on success.
Domain:[=Operation=]
Range includes: + `rdfs:Resource`, + [=Resource=], + `rdfs:Class`, + [=Class=] +
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api?documentation", + "@type": "ApiDocumentation", + "entrypoint": "http://api.example.com/api", + "extension": "https://w3id.org/hydra/extension#shacl", + "supportedClass": [ + { + "@id": "http://api.example.com/vocab#User", + "title": "User", + "description": "Describes a system user.", + "supportedOperation": [ + { + "method": "PUT", + "title": "Create new user", + "description": "Creates a brand new user.", + "expects": "http://api.example.com/vocab#User", + "returns": "http://api.example.com/vocab#User", + "returnsHeader": [ + { + "headerName": "Content-Type", + "possibleValue": ["text/turtle", "application/ld+json"], + "closedSet": true + } + "Content-Length" + ], + "expectsHeader": [ + "Authorization", + { + "headerName": "Content-Type", + "possibleValue": ["image/gif", "image/png"], + "closedSet": true + } + ] + } + ], + "supportedProperty": [ + { + "property": "http://api.example.com/vocab#login", + "writable": true, + "readable": true, + "required": true + } + ] + } + ] +} + +
+ +## hydra:returnsHeader ## {#property-returnsHeader} + + + + + + + + + + + + + + + + + +
Name:returnsHeader
Summary:Name of the header returned by the operation.
Domain:[=Operation=]
Range includes: + `xsd:string`, + [=HeaderSpecification=] +
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api?documentation", + "@type": "ApiDocumentation", + "entrypoint": "http://api.example.com/api", + "extension": "https://w3id.org/hydra/extension#shacl", + "supportedClass": [ + { + "@id": "http://api.example.com/vocab#User", + "title": "User", + "description": "Describes a system user.", + "supportedOperation": [ + { + "method": "PUT", + "title": "Create new user", + "description": "Creates a brand new user.", + "expects": "http://api.example.com/vocab#User", + "returns": "http://api.example.com/vocab#User", + "returnsHeader": [ + { + "headerName": "Content-Type", + "possibleValue": ["text/turtle", "application/ld+json"], + "closedSet": true + } + "Content-Length" + ], + "expectsHeader": [ + "Authorization", + { + "headerName": "Content-Type", + "possibleValue": ["image/gif", "image/png"], + "closedSet": true + } + ] + } + ], + "supportedProperty": [ + { + "property": "http://api.example.com/vocab#login", + "writable": true, + "readable": true, + "required": true + } + ] + } + ] +} + +
+ +## hydra:search ## {#property-search} + + + + + + + + + + + + + + + + + +
Name:search
Summary:A Iri template that can be used to query a collection.
Domain:[=Resource=]
Range:[=IriTemplate=]
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api/posts", + "@type": "Collection", + "view": { + "@id": "http://api.example.com/api/posts?skip=10", + "@type": "PartialCollectionView", + "first": "http://api.example.com/api/posts", + "last": "http://api.example.com/api/posts?skip=100", + "previous": "http://api.example.com/api/posts", + "next": "http://api.example.com/api/posts?skip=20", + "totalItems": 10, + }, + "totalItems": 100, + "member": [ + { "@id": "http://api.example.com/api/posts/10" }, + { "@id": "http://api.example.com/api/posts/11" }, + { "@id": "http://api.example.com/api/posts/12" }, + { "@id": "http://api.example.com/api/posts/13" }, + { "@id": "http://api.example.com/api/posts/14" }, + { "@id": "http://api.example.com/api/posts/15" }, + { "@id": "http://api.example.com/api/posts/16" }, + { "@id": "http://api.example.com/api/posts/17" }, + { "@id": "http://api.example.com/api/posts/18" }, + { "@id": "http://api.example.com/api/posts/19" } + ], + "search": { + "template": "/api/posts{?search,limit,offset}", + "resolveRelativeUsing": "hydra:Rfc3986", + "mapping": [ + { + "variable": "search", + "property": "hydra:freetextQuery", + "required": true, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "limit", + "property": "hydra:limit", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "offset", + "property": "hydra:offset", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + } + ] + } +} + +
+ +## hydra:statusCode ## {#property-statusCode} + + + + + + + + + + + + + + + + + +
Name:statusCode
Summary: + The response status code. Please note it may happen this + value will be different to actual status code received. +
Domain:[=Status=]
Range:`xsd:integer`
+
+ +HTTP/1.1 400 Bad request +Content-Type: application/problem+json +Link: <http://www.w3.org/ns/hydra/error>; rel="http://www.w3.org/ns/json-ld#context" + +{ + "type": "https://api.example.com/vocab#NullReferenceException", + "@type": "http://www.w3.org/ns/hydra/core#Error", + "title": "The request cannot be processed.", + "detail": "Provided value cannot be 'null'.", + "instance": "http://api.example.com/api/posts", + "status": 404 +} + +
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api/posts/1", + "operation": [ + { + "method": "DELETE", + "title": "Remove", + "description": "Removes post no. 1", + "possibleStatus": [ + { + "@type": "Status", + "statusCode": 303 + } + ] + } + ] +} + +
+ +## hydra:subject ## {#property-subject} + + + + + + + + + + + + + +
Name:subject
Summary:The subject.
Min cardinality:1
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api/posts/1/comments", + "@type": "Collection", + "memberAssertion": [ + { + "subject": "http://api.example.com/api/posts/1", + "property": "http://api.example.com/vocab#comment" + } + ] +} + +
+ +## hydra:supportedClass ## {#property-supportedClass} + + + + + + + + + + + + + + + + + +
Name:supportedClass
Summary:A class known to be supported by the Web API.
Domain:[=ApiDocumentation=]
Range:`rdfs:Class`
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api?documentation", + "@type": "ApiDocumentation", + "entrypoint": "http://api.example.com/api", + "extension": "https://w3id.org/hydra/extension#shacl", + "supportedClass": [ + { + "@id": "http://api.example.com/vocab#User", + "title": "User", + "description": "Describes a system user.", + "supportedOperation": [ + { + "method": "PUT", + "title": "Create new user", + "description": "Creates a brand new user.", + "expects": "http://api.example.com/vocab#User", + "returns": "http://api.example.com/vocab#User", + "returnsHeader": [ + { + "headerName": "Content-Type", + "possibleValue": ["text/turtle", "application/ld+json"], + "closedSet": true + } + "Content-Length" + ], + "expectsHeader": [ + "Authorization", + { + "headerName": "Content-Type", + "possibleValue": ["image/gif", "image/png"], + "closedSet": true + } + ] + } + ], + "supportedProperty": [ + { + "property": "http://api.example.com/vocab#login", + "writable": true, + "readable": true, + "required": true + } + ] + } + ] +} + +
+ +## hydra:supportedOperation ## {#property-supportedOperation} + + + + + + + + + + + + + + + + + +
Name:supportedOperation
Summary: + An operation supported by instances of the specific Hydra + class, or the target of the Hydra link, or Iri template. +
Domain includes: + `rdfs:Class`, + [=Class=], + [=Link=], + [=TemplatedLink=], + [=SupportedProperty=] +
Range:[=Operation=]
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api?documentation", + "@type": "ApiDocumentation", + "entrypoint": "http://api.example.com/api", + "extension": "https://w3id.org/hydra/extension#shacl", + "supportedClass": [ + { + "@id": "http://api.example.com/vocab#User", + "title": "User", + "description": "Describes a system user.", + "supportedOperation": [ + { + "method": "PUT", + "title": "Create new user", + "description": "Creates a brand new user.", + "expects": "http://api.example.com/vocab#User", + "returns": "http://api.example.com/vocab#User", + "returnsHeader": [ + { + "headerName": "Content-Type", + "possibleValue": ["text/turtle", "application/ld+json"], + "closedSet": true + } + "Content-Length" + ], + "expectsHeader": [ + "Authorization", + { + "headerName": "Content-Type", + "possibleValue": ["image/gif", "image/png"], + "closedSet": true + } + ] + } + ], + "supportedProperty": [ + { + "property": "http://api.example.com/vocab#login", + "writable": true, + "readable": true, + "required": true + } + ] + } + ] +} + +
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api/posts", + "@type": "Collection", + "view": { + "@id": "http://api.example.com/api/posts?skip=10", + "@type": "PartialCollectionView", + "first": "http://api.example.com/api/posts", + "last": "http://api.example.com/api/posts?skip=100", + "previous": "http://api.example.com/api/posts", + "next": "http://api.example.com/api/posts?skip=20", + "totalItems": 10, + }, + "totalItems": 100, + "member": [ + { "@id": "http://api.example.com/api/posts/10" }, + { "@id": "http://api.example.com/api/posts/11" }, + { "@id": "http://api.example.com/api/posts/12" }, + { "@id": "http://api.example.com/api/posts/13" }, + { "@id": "http://api.example.com/api/posts/14" }, + { "@id": "http://api.example.com/api/posts/15" }, + { "@id": "http://api.example.com/api/posts/16" }, + { "@id": "http://api.example.com/api/posts/17" }, + { "@id": "http://api.example.com/api/posts/18" }, + { "@id": "http://api.example.com/api/posts/19" } + ], + "search": { + "template": "/api/posts{?search}", + "resolveRelativeUsing": "hydra:Rfc3986", + "supportedOperation": { + "method": "POST" + }, + "mapping": [ + { + "variable": "search", + "property": "hydra:freetextQuery", + "required": true, + "variableRepresentation": "hydra:BasicRepresentation" + } + ] + } +} + +
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@graph": [ + { + "@id": "http://api.example.com/api/posts/1", + "http://api.example.com/vocab#comment": + "http://api.example.com/api/posts/1/comments" + }, + { + "@id": "http://api.example.com/vocab#comment", + "@type": "hydra:Link", + "supportedOperation": { + "method": "GET", + "returns": "http://api.example.com/vocab#Comment + } + } + ] +} + +
+ +## hydra:supportedProperty ## {#property-supportedProperty} + + + + + + + + + + + + + + + + + +
Name:supportedProperty‎
Summary:The properties known to be supported by a Hydra class.
Domain:`rdfs:Class`
Range:[=SupportedProperty=]
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api?documentation", + "@type": "ApiDocumentation", + "entrypoint": "http://api.example.com/api", + "extension": "https://w3id.org/hydra/extension#shacl", + "supportedClass": [ + { + "@id": "http://api.example.com/vocab#User", + "title": "User", + "description": "Describes a system user.", + "supportedOperation": [ + { + "method": "PUT", + "title": "Create new user", + "description": "Creates a brand new user.", + "expects": "http://api.example.com/vocab#User", + "returns": "http://api.example.com/vocab#User", + "returnsHeader": [ + { + "headerName": "Content-Type", + "possibleValue": ["text/turtle", "application/ld+json"], + "closedSet": true + } + "Content-Length" + ], + "expectsHeader": [ + "Authorization", + { + "headerName": "Content-Type", + "possibleValue": ["image/gif", "image/png"], + "closedSet": true + } + ] + } + ], + "supportedProperty": [ + { + "property": "http://api.example.com/vocab#login", + "writable": true, + "readable": true, + "required": true + } + ] + } + ] +} + +
+ +## hydra:template ## {#property-template} + + + + + + + + + + + + + + + + + + + + + + + + + +
Name:template
Summary: + A templated string with placeholders. The literal's + datatype indicates the template syntax; if not specified, + hydra:Rfc6570Template is assumed. +
Min cardinality:1
Max cardinality:1
Domain:[=IriTemplate=]
Range:[=Rfc6570Template=]
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api/posts", + "@type": "Collection", + "view": { + "@id": "http://api.example.com/api/posts?skip=10", + "@type": "PartialCollectionView", + "first": "http://api.example.com/api/posts", + "last": "http://api.example.com/api/posts?skip=100", + "previous": "http://api.example.com/api/posts", + "next": "http://api.example.com/api/posts?skip=20", + "totalItems": 10, + }, + "totalItems": 100, + "member": [ + { "@id": "http://api.example.com/api/posts/10" }, + { "@id": "http://api.example.com/api/posts/11" }, + { "@id": "http://api.example.com/api/posts/12" }, + { "@id": "http://api.example.com/api/posts/13" }, + { "@id": "http://api.example.com/api/posts/14" }, + { "@id": "http://api.example.com/api/posts/15" }, + { "@id": "http://api.example.com/api/posts/16" }, + { "@id": "http://api.example.com/api/posts/17" }, + { "@id": "http://api.example.com/api/posts/18" }, + { "@id": "http://api.example.com/api/posts/19" } + ], + "search": { + "template": "/api/posts{?search,limit,offset}", + "resolveRelativeUsing": "hydra:Rfc3986", + "mapping": [ + { + "variable": "search", + "property": "hydra:freetextQuery", + "required": true, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "limit", + "property": "hydra:limit", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "offset", + "property": "hydra:offset", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + } + ] + } +} + +
+ +## hydra:title ## {#property-title} + + + + + + + + + + + + + + + + + + + + + +
Name:title
Summary:A title, often used along with a description.
Max cardinality:1
Domain includes: + [=ApiDocumentation=], + [=Status=], + [=Class=], + [=SupportedProperty=], + [=Operation=], + [=Link=], + [=TemplatedLink=] +
Range:`xsd:string`
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api?documentation", + "@type": "ApiDocumentation", + "entrypoint": "http://api.example.com/api", + "extension": "https://w3id.org/hydra/extension#shacl", + "supportedClass": [ + { + "@id": "http://api.example.com/vocab#User", + "title": "User", + "description": "Describes a system user.", + "supportedOperation": [ + { + "method": "PUT", + "title": "Create new user", + "description": "Creates a brand new user.", + "expects": "http://api.example.com/vocab#User", + "returns": "http://api.example.com/vocab#User", + "returnsHeader": [ + { + "headerName": "Content-Type", + "possibleValue": ["text/turtle", "application/ld+json"], + "closedSet": true + } + "Content-Length" + ], + "expectsHeader": [ + "Authorization", + { + "headerName": "Content-Type", + "possibleValue": ["image/gif", "image/png"], + "closedSet": true + } + ] + } + ], + "supportedProperty": [ + { + "property": "http://api.example.com/vocab#login", + "writable": true, + "readable": true, + "required": true + } + ] + } + ] +} + +
+ +## hydra:totalItems ## {#property-totalItems} + + + + + + + + + + + + + + + + + + + + + +
Name:totalItems
Summary:The total number of items referenced by a collection.
Max cardinality:1
Domain:[=Collection=]
Range:`xsd:integer`
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api/posts", + "@type": "Collection", + "view": { + "@id": "http://api.example.com/api/posts?skip=10", + "@type": "PartialCollectionView", + "first": "http://api.example.com/api/posts", + "last": "http://api.example.com/api/posts?skip=100", + "previous": "http://api.example.com/api/posts", + "next": "http://api.example.com/api/posts?skip=20", + "totalItems": 10, + }, + "totalItems": 100, + "member": [ + { "@id": "http://api.example.com/api/posts/10" }, + { "@id": "http://api.example.com/api/posts/11" }, + { "@id": "http://api.example.com/api/posts/12" }, + { "@id": "http://api.example.com/api/posts/13" }, + { "@id": "http://api.example.com/api/posts/14" }, + { "@id": "http://api.example.com/api/posts/15" }, + { "@id": "http://api.example.com/api/posts/16" }, + { "@id": "http://api.example.com/api/posts/17" }, + { "@id": "http://api.example.com/api/posts/18" }, + { "@id": "http://api.example.com/api/posts/19" } + ], + "search": { + "template": "/api/posts{?search,limit,offset}", + "resolveRelativeUsing": "hydra:Rfc3986", + "mapping": [ + { + "variable": "search", + "property": "hydra:freetextQuery", + "required": true, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "limit", + "property": "hydra:limit", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "offset", + "property": "hydra:offset", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + } + ] + } +} + +
+ +## hydra:variable ## {#property-variable} + + + + + + + + + + + + + + + + + + + + + + + + + +
Name:variable
Summary:An Iri template variable.
Min cardinality:1
Max cardinality:1
Domain:[=IriTemplateMapping=]
Range:`xsd:string`
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api/posts", + "@type": "Collection", + "view": { + "@id": "http://api.example.com/api/posts?skip=10", + "@type": "PartialCollectionView", + "first": "http://api.example.com/api/posts", + "last": "http://api.example.com/api/posts?skip=100", + "previous": "http://api.example.com/api/posts", + "next": "http://api.example.com/api/posts?skip=20", + "totalItems": 10, + }, + "totalItems": 100, + "member": [ + { "@id": "http://api.example.com/api/posts/10" }, + { "@id": "http://api.example.com/api/posts/11" }, + { "@id": "http://api.example.com/api/posts/12" }, + { "@id": "http://api.example.com/api/posts/13" }, + { "@id": "http://api.example.com/api/posts/14" }, + { "@id": "http://api.example.com/api/posts/15" }, + { "@id": "http://api.example.com/api/posts/16" }, + { "@id": "http://api.example.com/api/posts/17" }, + { "@id": "http://api.example.com/api/posts/18" }, + { "@id": "http://api.example.com/api/posts/19" } + ], + "search": { + "template": "/api/posts{?search,limit,offset}", + "resolveRelativeUsing": "hydra:Rfc3986", + "mapping": [ + { + "variable": "search", + "property": "hydra:freetextQuery", + "required": true, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "limit", + "property": "hydra:limit", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "offset", + "property": "hydra:offset", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + } + ] + } +} + +
+ +## hydra:variableRepresentation ## {#property-variableRepresentation} + + + + + + + + + + + + + + + + + + + + + +
Name:variableRepresentation‎
Summary: + The representation format to use when expanding + the Iri template. +
Max cardinality:1
Domain:[=IriTemplateMapping=]
Range:[=VariableRepresentation=]
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api/posts", + "@type": "Collection",hydra:view + "view": { + "@id": "http://api.example.com/api/posts?skip=10", + "@type": "PartialCollectionView", + "first": "http://api.example.com/api/posts", + "last": "http://api.example.com/api/posts?skip=100", + "previous": "http://api.example.com/api/posts", + "next": "http://api.example.com/api/posts?skip=20", + "totalItems": 10, + }, + "totalItems": 100, + "member": [ + { "@id": "http://api.example.com/api/posts/10" }, + { "@id": "http://api.example.com/api/posts/11" }, + { "@id": "http://api.example.com/api/posts/12" }, + { "@id": "http://api.example.com/api/posts/13" }, + { "@id": "http://api.example.com/api/posts/14" }, + { "@id": "http://api.example.com/api/posts/15" }, + { "@id": "http://api.example.com/api/posts/16" }, + { "@id": "http://api.example.com/api/posts/17" }, + { "@id": "http://api.example.com/api/posts/18" }, + { "@id": "http://api.example.com/api/posts/19" } + ], + "search": { + "template": "/api/posts{?search,limit,offset}", + "resolveRelativeUsing": "hydra:Rfc3986", + "mapping": [ + { + "variable": "search", + "property": "hydra:freetextQuery", + "required": true, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "limit", + "property": "hydra:limit", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "offset", + "property": "hydra:offset", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + } + ] + } +} + +
+ +## hydra:view ## {#property-view} + + + + + + + + + + + + + +
Name:view
Summary:A specific view of a resource.
Max cardinality:1
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api/posts", + "@type": "Collection", + "view": { + "@id": "http://api.example.com/api/posts?skip=10", + "@type": "PartialCollectionView", + "first": "http://api.example.com/api/posts", + "last": "http://api.example.com/api/posts?skip=100", + "previous": "http://api.example.com/api/posts", + "next": "http://api.example.com/api/posts?skip=20", + "totalItems": 10, + }, + "totalItems": 100, + "member": [ + { "@id": "http://api.example.com/api/posts/10" }, + { "@id": "http://api.example.com/api/posts/11" }, + { "@id": "http://api.example.com/api/posts/12" }, + { "@id": "http://api.example.com/api/posts/13" }, + { "@id": "http://api.example.com/api/posts/14" }, + { "@id": "http://api.example.com/api/posts/15" }, + { "@id": "http://api.example.com/api/posts/16" }, + { "@id": "http://api.example.com/api/posts/17" }, + { "@id": "http://api.example.com/api/posts/18" }, + { "@id": "http://api.example.com/api/posts/19" } + ], + "search": { + "template": "/api/posts{?search,limit,offset}", + "resolveRelativeUsing": "hydra:Rfc3986", + "mapping": [ + { + "variable": "search", + "property": "hydra:freetextQuery", + "required": true, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "limit", + "property": "hydra:limit", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + }, + { + "variable": "offset", + "property": "hydra:offset", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation" + } + ] + } +} + +
+ +## hydra:writable ## {#property-writable} + + + + + + + + + + + + + + + + + + + + + +
Name:writable
Summary: + True if the client can change the property's value, + false otherwise. +
Max cardinality:1
Domain:[=SupportedProperty=]
Range:`xsd:boolean`
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api?documentation", + "@type": "ApiDocumentation", + "entrypoint": "http://api.example.com/api", + "extension": "https://w3id.org/hydra/extension#shacl", + "supportedClass": [ + { + "@id": "http://api.example.com/vocab#User", + "label": "User", + "description": "Describes a system user.", + "supportedOperation": [ + { + "method": "PUT", + "label": "Create new user", + "description": "Creates a brand new user.", + "expects": "http://api.example.com/vocab#User", + "returns": "http://api.example.com/vocab#User", + "returnsHeader": [ + { + "headerName": "Content-Type", + "possibleValue": ["text/turtle", "application/ld+json"], + "closedSet": true + } + "Content-Length" + ], + "expectsHeader": [ + "Authorization", + { + "headerName": "Content-Type", + "possibleValue": ["image/gif", "image/png"], + "closedSet": true + } + ] + } + ], + "supportedProperty": [ + { + "property": "http://api.example.com/vocab#login", + "writable": true, + "readable": true, + "required": true + } + ] + } + ] +} + +
+ +Named instances {#named-instances} +=============== + +## hydra:BasicRepresentation ## {#instance-BasicRepresentation} + + + + + + + + + + + + + +
Name:BasicRepresentation
Summary: + A representation that serializes just the lexical form of a variable value, + but omits language and type information. +
Sub-class of:[=VariableRepresentation=]
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api/posts", + "@type": "Collection", + "view": { + "@id": "http://api.example.com/api/posts?skip=10", + "@type": "PartialCollectionView", + "first": "http://api.example.com/api/posts", + "last": "http://api.example.com/api/posts?skip=100", + "previous": "http://api.example.com/api/posts", + "next": "http://api.example.com/api/posts?skip=20", + "totalItems": 10, + }, + "totalItems": 100, + "member": [ + { "@id": "http://api.example.com/api/posts/10" }, + { "@id": "http://api.example.com/api/posts/11" }, + { "@id": "http://api.example.com/api/posts/12" }, + { "@id": "http://api.example.com/api/posts/13" }, + { "@id": "http://api.example.com/api/posts/14" }, + { "@id": "http://api.example.com/api/posts/15" }, + { "@id": "http://api.example.com/api/posts/16" }, + { "@id": "http://api.example.com/api/posts/17" }, + { "@id": "http://api.example.com/api/posts/18" }, + { "@id": "http://api.example.com/api/posts/19" } + ], + "search": { + "template": "/api/posts{?search}", + "resolveRelativeUsing": "hydra:Rfc3986", + "mapping": [ + { + "variable": "search", + "property": "hydra:freetextQuery", + "required": true, + "variableRepresentation": "hydra:BasicRepresentation" + } + ] + } +} + +
+ +## hydra:ExplicitRepresentation ## {#instance-ExplicitRepresentation} + + + + + + + + + + + + + +
Name:ExplicitRepresentation
Summary: + A representation that serializes a variable value including its language + and type information and thus differentiating between IRIs and literals. +
Sub-class of:[=VariableRepresentation=]
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api/posts", + "@type": "Collection", + "view": { + "@id": "http://api.example.com/api/posts?skip=10", + "@type": "PartialCollectionView", + "first": "http://api.example.com/api/posts", + "last": "http://api.example.com/api/posts?skip=100", + "previous": "http://api.example.com/api/posts", + "next": "http://api.example.com/api/posts?skip=20", + "totalItems": 10, + }, + "totalItems": 100, + "member": [ + { "@id": "http://api.example.com/api/posts/10" }, + { "@id": "http://api.example.com/api/posts/11" }, + { "@id": "http://api.example.com/api/posts/12" }, + { "@id": "http://api.example.com/api/posts/13" }, + { "@id": "http://api.example.com/api/posts/14" }, + { "@id": "http://api.example.com/api/posts/15" }, + { "@id": "http://api.example.com/api/posts/16" }, + { "@id": "http://api.example.com/api/posts/17" }, + { "@id": "http://api.example.com/api/posts/18" }, + { "@id": "http://api.example.com/api/posts/19" } + ], + "search": { + "template": "/api/posts{?search}", + "resolveRelativeUsing": "hydra:Rfc3986", + "mapping": [ + { + "variable": "search", + "property": "hydra:freetextQuery", + "required": true, + "variableRepresentation": "hydra:ExplicitRepresentation" + } + ] + } +} + +
+ +## hydra:LinkContext ## {#instance-LinkContext} + + + + + + + + + + + + + +
Name:LinkContext
Summary: + States that the link's context IRI, as defined in RFC 5988, should be used + as the base Uri. +
Sub-class of:[=BaseUriSource=]
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api/posts", + "@type": "Collection", + "view": { + "@id": "http://api.example.com/api/posts?skip=10", + "@type": "PartialCollectionView", + "first": "http://api.example.com/api/posts", + "last": "http://api.example.com/api/posts?skip=100", + "previous": "http://api.example.com/api/posts", + "next": "http://api.example.com/api/posts?skip=20", + "totalItems": 10, + }, + "totalItems": 100, + "member": [ + { "@id": "http://api.example.com/api/posts/10" }, + { "@id": "http://api.example.com/api/posts/11" }, + { "@id": "http://api.example.com/api/posts/12" }, + { "@id": "http://api.example.com/api/posts/13" }, + { "@id": "http://api.example.com/api/posts/14" }, + { "@id": "http://api.example.com/api/posts/15" }, + { "@id": "http://api.example.com/api/posts/16" }, + { "@id": "http://api.example.com/api/posts/17" }, + { "@id": "http://api.example.com/api/posts/18" }, + { "@id": "http://api.example.com/api/posts/19" } + ], + "search": { + "template": { + "@value": "/api/posts{?search}", + "@type": "hydra:Rfc6570Template" + }, + "resolveRelativeUsing": "hydra:LinkContext", + "mapping": [ + { + "variable": "search", + "property": "hydra:freetextQuery", + "required": true, + "variableRepresentation": "hydra:BasicRepresentation" + } + ] + } +} + +
+ +## hydra:Rfc3986 ## {#instance-Rfc3986} + + + + + + + + + + + + + +
Name:Rfc3986
Summary: + States that the link's context IRI, as defined in RFC 5988, should be used + as the base Uri. +
Sub-class of:[=BaseUriSource=]
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api/posts", + "@type": "Collection", + "view": { + "@id": "http://api.example.com/api/posts?skip=10", + "@type": "PartialCollectionView", + "first": "http://api.example.com/api/posts", + "last": "http://api.example.com/api/posts?skip=100", + "previous": "http://api.example.com/api/posts", + "next": "http://api.example.com/api/posts?skip=20", + "totalItems": 10, + }, + "totalItems": 100, + "member": [ + { "@id": "http://api.example.com/api/posts/10" }, + { "@id": "http://api.example.com/api/posts/11" }, + { "@id": "http://api.example.com/api/posts/12" }, + { "@id": "http://api.example.com/api/posts/13" }, + { "@id": "http://api.example.com/api/posts/14" }, + { "@id": "http://api.example.com/api/posts/15" }, + { "@id": "http://api.example.com/api/posts/16" }, + { "@id": "http://api.example.com/api/posts/17" }, + { "@id": "http://api.example.com/api/posts/18" }, + { "@id": "http://api.example.com/api/posts/19" } + ], + "search": { + "template": { + "@value": "/api/posts{?search}", + "@type": "hydra:Rfc6570Template" + }, + "resolveRelativeUsing": "hydra:Rfc3986", + "mapping": [ + { + "variable": "search", + "property": "hydra:freetextQuery", + "required": true, + "variableRepresentation": "hydra:BasicRepresentation" + } + ] + } +} + +
+ +Data types {#data-types} +========== + +## hydra:Rfc6570Template ## {#datatype-Rfc6570Template} + + + + + + + + + +
Name:Rfc6570Template
Summary:An IRI template as defined by [[!RFC6570]].
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/api/posts", + "@type": "Collection", + "view": { + "@id": "http://api.example.com/api/posts?skip=10", + "@type": "PartialCollectionView", + "first": "http://api.example.com/api/posts", + "last": "http://api.example.com/api/posts?skip=100", + "previous": "http://api.example.com/api/posts", + "next": "http://api.example.com/api/posts?skip=20", + "totalItems": 10, + }, + "totalItems": 100, + "member": [ + { "@id": "http://api.example.com/api/posts/10" }, + { "@id": "http://api.example.com/api/posts/11" }, + { "@id": "http://api.example.com/api/posts/12" }, + { "@id": "http://api.example.com/api/posts/13" }, + { "@id": "http://api.example.com/api/posts/14" }, + { "@id": "http://api.example.com/api/posts/15" }, + { "@id": "http://api.example.com/api/posts/16" }, + { "@id": "http://api.example.com/api/posts/17" }, + { "@id": "http://api.example.com/api/posts/18" }, + { "@id": "http://api.example.com/api/posts/19" } + ], + "search": { + "template": { + "@value": "/api/posts{?search,limit,offset}", + "@type": "hydra:Rfc6570Template" + }, + "resolveRelativeUsing": "hydra:Rfc3986", + "mapping": [ + { + "variable": "search", + "property": "hydra:freetextQuery", + "required": true, + "variableRepresentation": "hydra:BasicRepresentation"" + }, + { + "variable": "limit", + "property": "hydra:limit", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation"" + }, + { + "variable": "offset", + "property": "hydra:offset", + "required": false, + "variableRepresentation": "hydra:BasicRepresentation"" + } + ] + } +} + +
+ +Acknowledgements {#acknowledgments} +================ + +Note: This section is non-normative. + +The authors would like to thank the following individuals for contributing +their ideas and providing feedback for writing this specification: +Arnau Siches, elf Pavlik, Karol Szczepański, Mark Baker, Martijn Faassen, +Matthias Lehmann, Ruben Verborgh, Ryan J. McDonough, Sam Goto, +Thomas Hoppe, Tomasz Pluskiewicz, @wasabiwimp (on GitHub). + +The Hydra in JSON-LD {#vocab-jsonld} +==================================== + +Note: This section is non-normative. + +
+path: core.jsonld
+highlight: json-ld
+
+ +The Hydra error context {#error-jsonld} +====================================================== + +Note: This section is non-normative. + +
+path: error.jsonld
+highlight: json-ld
+
+ +
+{
+	"HydraCG": {
+		"href": "https://www.w3.org/community/hydra/",
+		"title": "Hydra W3C Community Group"
+	}
+}
+
\ No newline at end of file diff --git a/spec/latest/core/index.html b/spec/latest/core/index.html index 9e9039a..cd7a4fa 100644 --- a/spec/latest/core/index.html +++ b/spec/latest/core/index.html @@ -1,1655 +1,5224 @@ - - - -Hydra Core Vocabulary - - - - - + + + + Hydra Core Vocabulary + + + + + + + + + + + + + - - - -
-

Hydra is a lightweight vocabulary to create hypermedia-driven Web APIs. - By specifying a number of concepts commonly used in Web APIs it enables - the creation of generic API clients.

-
- -
-

This entire document is a work in progress and several - sections are incomplete, missing, or outdated. All open issues and decisions - are documented in our - issue tracker. - If you have questions, please don't hesitate to - join the Hydra W3C Community Group and post to the mailing list. -

- -

This specification was published by the - Hydra W3C Community Group. It is - not a W3C Standard nor is it on the W3C Standards Track. Please note that under the - W3C Community Contributor License Agreement (CLA) - there is a limited opt-out and other conditions apply. Learn more about - W3C Community and Business Groups.

- -

To participate in the development of this specification, please join the - Hydra W3C Community Group. If - you have questions, want to suggest a feature, or raise an issue, please send a mail to the - public-hydra@w3.org mailing list.

-
- -
-

Introduction

- -

Coping with the ever-increasing amount of data becomes - increasingly challenging. To alleviate the information overload put on - people, systems are progressively being connected directly to each - other. They exchange, analyze, and manipulate humongous amounts of - data without any human interaction. Most current solutions, however, - do not exploit the whole potential of the architecture of the World - Wide Web and completely ignore the possibilities offered by Linked Data - technologies.

- -

The combination of the REST architectural style and the Linked - Data principles offer opportunities to advance the Web of machines - in a similar way that hypertext did for the human Web. Most - building blocks exist already and are in place but they are rarely - used together. Hydra tries to fill that gap. It allows data to be - enriched with machine-readable affordances which enable - interaction. This not only addresses the problem that Linked Data - is still mostly read-only, but it also paves the way for a - completely new breed of interoperable Web APIs. The fact that it - enables the creation of composable contracts means that - interaction models of Web APIs can be reused at an unprecedented - granularity.

-
- -
-

Conformance

- -

This specification describes the conformance criteria for - Hydra API documentations - and Hydra clients. These criteria are - relevant to authors, authoring tool implementers, and client - implementers. All authoring guidelines, diagrams, examples, and notes - in this specification are non-normative, as are all sections - explicitly marked as non-normative. Everything else in this - specification is normative.

- -

Conformance for Hydra clients should probably not be - specified in this document.

- -

Add normative statements

- -

The key words MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, - SHOULD NOT, RECOMMENDED, NOT RECOMMENDED, MAY, and OPTIONAL in this - specification have the meaning defined in [[!RFC2119]].

-
- -
-

Hydra at a Glance

- -

The basic idea behind Hydra is to provide a vocabulary which enables a - server to advertise valid state transitions to a client. A client can - then use this information to construct HTTP requests which modify the - server’s state so that a certain desired goal is achieved. Since all - the information about the valid state transitions is exchanged in a - machine-processable way at runtime instead of being hardcoded into the - client at design time, clients can be decoupled from the server and - adapt to changes more easily.

- -

The namespace of the Hydra core vocabulary is - http://www.w3.org/ns/hydra/core#, and the suggested prefix - is hydra. The figure below illustrates the vocabulary (the - figure’s goal is to show how Hydra is used rather than its precise - definition).

- -

Is this illustration clear enough or is it confusing? - Feedback would be much appreciated.

- -
-

The Hydra core vocabulary

-

The Hydra core vocabulary

+ + +
+

+

Hydra Core Vocabulary

+

Living Document,

+
+
+
This version: +
https://www.hydra-cg.com/spec/latest/core/ +
Editors: +
Markus Lanthaler +
Karol Szczepanski +
Author: +
Markus Lanthaler +
Karol Szczepanski +
+
+
+ +
+
+
+

Abstract

+

Hydra is a lightweight vocabulary to create hypermedia-driven Web APIs. By specifying a number of concepts commonly used in Web APIs it enables the creation of generic API clients.

+
+ +
+

1. Status of This Document

+ This specification was published by the [HydraCG]. +It is not a W3C Standard, nor it is on the W3C Standards Track. +Please note that under the W3C Community Contributor License Agreement (CLA) there is a limited opt-out and other conditions apply. +Learn more about W3C Community and Business Groups. +

1.1. Conventions

+

Within this document, the following namespace prefix bindings are used:

+ + + + + + + + + + + + +
Prefix + Namespace +
hydra: + http://www.w3.org/ns/hydra/core# +
rdf: + http://www.w3.org/1999/02/22-rdf-syntax-ns# +
rdfs: + http://www.w3.org/2000/01/rdf-schema# +
xsd: + http://www.w3.org/2001/XMLSchema# +
owl: + http://www.w3.org/2002/07/owl# +
vs: + http://www.w3.org/2003/06/sw-vocab-status/ns# +
dc: + http://purl.org/dc/terms/ +
cc: + http://creativecommons.org/ns# +
schema: + http://schema.org/ +
+

2. Introduction

+

Note: This section is non-normative.

+

Coping with the ever-increasing amount of data becomes increasingly +challenging. To alleviate the information overload put on people, +systems are progressively being connected directly to each other. +They exchange, analyze, and manipulate humongous amounts of data +without any human interaction. Most current solutions, however, +do not exploit the whole potential of the architecture of the World +Wide Web and completely ignore the possibilities offered by Linked Data +technologies.

+

The combination of the REST architectural style, and the Linked +Data principles offer opportunities to advance the Web of machines +in a similar way that hypertext did for the human Web. Most +building blocks exist already and are in place, but they are rarely +used together. Hydra tries to fill that gap. It allows data +to be enriched with machine-readable affordances which enable interaction. +This not only addresses the problem that Linked Data is still mostly +read-only, but it also paves the way for a completely new breed +of interoperable Web APIs. The fact that it enables the creation +of composable contracts means that interaction models of Web APIs +can be reused at an unprecedented granularity.

+

3. Hydra at a Glance

+

Note: This section is non-normative.

+

The basic idea behind Hydra is to provide a vocabulary which enables a +server to advertise valid state transitions to a client. A client can +then use this information to construct requests (i.e. compliant with +an HTTP protocol) which modify the server’s state so that a certain +desired goal is achieved. Since all the information about the valid state +transitions is exchanged in a machine-processable way at runtime +instead of being hardcoded into the client at design time, clients +can be decoupled from the server and adapt to changes more easily.

+

The namespace of the Hydra core vocabulary +is http://www.w3.org/ns/hydra/core#, and the suggested prefix +is hydra. The figure below illustrates the vocabulary +(the figure’s goal is to show how Hydra is used rather than its precise +definition).

+

The Hydra core vocabulary

+

An alphabetical index of the classes and properties of Hydra +is given below. All the terms are hyperlinked to their detailed +description for quick reference.

+

4. Using Hydra

+

Throughout this section, a simple Web API featuring an issue tracker +will be used to illustrate how Hydra can be used. The Web API enables +its users to file new issues, modify or delete existing ones, and +to comment them. For the sake of simplicity, orthogonal aspects such +as authentication or authorization are not covered.

+

4.1. Adding Affordances to Representations

+

The exemplary Web API has to expose representations of issues and +comments. To enable interaction with those resources, a client has +to know which operations the server supports. In human-facing +websites such affordances are typically exposed by links and forms +and described in natural language. Unfortunately, machines can not +interpret such information easily. The solution that presents itself +is to reduce the language to a few unambiguous concepts which are easily +recognizable by a machine client. Hydra formalizes such concepts.

+

The simplest and most important affordance on the Web are hyperlinks. +Without them, it would be impossible to browse the Web. +Users typically select the link based on the text it is labeled with. +To give machines a similar understanding, links can be annotated +with a link relation type—a registered token or a URI identifying +the semantics of the link. The following example shows how such +a typed link is used in HTML to reference a stylesheet.

+
+ +
EXAMPLE: A typed link referencing a stylesheet as used in HTML
+
<link href="http://www.example.com/styles.css"      rel="stylesheet" />
+
+

In Linked Data, the link relation type corresponds to the property itself. +An example in JSON-LD would thus look as follows.

+
+ +
EXAMPLE: Referencing a stylesheet in JSON-LD
+
{    "urn:iana:link-relations:stylesheet": {        "@id": "http://www.example.com/styles.css"    }}
+
+

Generally, a client decides whether to follow a link or not based on +the link relation (or property in the case of Linked Data) which +defines its semantics. There are however also clients such as Web crawlers +which simply follow every link intended to be dereferenced. In HTML this +usually means that all links in anchor elements +(the <a> tag) are followed, but most references in link +elements (the <link> tag), such as used in the example +above, are ignored. Since in RDF serializations no such distinction exists, +the best a client can do is to blindly try to dereference all URIs. +It would thus be beneficial to describe in a machine-readable manner +if a property represents a link intended to be dereferenced or +solely an identifier. Hydra’s Link class does just that. It can be +used to define properties that represent dereferencable links. +In the exemplary Web API used throughout this section, it can be +used to define a property linking issues to their comments:

+
+ +
EXAMPLE: Defining properties representing hyperlinks using Hydra’s Link class
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/vocab#comments",    "@type": "Link"}
+
+

In the example above, a property identified with the URL http://api.example.com/vocab#comments is defined to be +of the type Link. This is enough information for a client understanding +Hydra to know that the value of the comments property +in the following example is intended to be dereferenced.

+

Note: It is recommended to dereference resources that are within an API’s domain. +This may prevent possible issues with cross-site scripting or obtaining +resources which might have no meaning to the client or such that the client +would be unable to interpret. Still, there is no formal prohibition of +dereferencing resources linked with well-known properties, e.g. rdf:seeAlso.

+
+ +
EXAMPLE: Using a property defined to be a hyperlink
+
{    "@context": {        "comments": "http://api.example.com/vocab#comments"    },    "@id": "http://api.example.com/an-issue",    "title": "An exemplary issue linking to its comments",    "comments": { "@id": "http://api.example.com/an-issue/comments" }}
+
+

In the example above, the value of the comments property +is a JSON object with an @id member. This is JSON-LD’s +convention to distinguish between strings and IRIs. By using JSON-LD’s +type-coercion feature, the representation can be made even more idiomatic:

+
+ +
EXAMPLE: Using JSON-LD’s type-coercion feature to create idiomatic representations
+
{    "@context": {        "comments": {            "@id": "http://api.example.com/vocab#comments",            "@type": "@id"        }    },    "@id": "http://api.example.com/an-issue",    "title": "An exemplary issue linking to its comments",    "comments":        "http://api.example.com/an-issue/comments"}
+
+

While links are enough to build read-only Web APIs, more powerful +affordances are required to build read-write Web APIs. Thus, Hydra +introduces the notion of operations. Simply speaking, an Operation represents the information necessary for a client +to construct valid HTTP requests in order to manipulate the server’s +resource state. As such, the only required property of an Operation is its method. Optionally, it is also possible +to describe what information the server expects or returns, +including additional information about response status codes that +might be returned. This helps a developer to understand what to expect +when invoking an operation. This information has, however, +not to be considered as being complete; it is merely a hint. +Developers should, e.g., expect that other status codes might be returned +and program their clients accordingly.

+

The following example illustrates how representations can be +augmented with information that enables clients to interact with +them.

+
+ +
EXAMPLE: A representation of an issue augmented with a delete operation
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "/an-issue",    "title": "An exemplary issue representation",    "description": "This issue can be deleted with an HTTP DELETE request.",    "operation": [        {            "@type": "Operation",            "method": "DELETE"        }    ]}
+
+

The example above references Hydra’s context to map properties such +as operation and method and values like Operation to URLs +that unambiguously identify these concepts. It would be similarly valid +JSON-LD if these mappings would be directly embedded into the representation +or if the full URLs would be used instead. Typically, however, the context +is the same for a lot of representations in a Web API and it thus makes +sense to reduce the response size by leveraging a remote context that +can easily be cached by a client.

+

Note: It is worth mentioning that due to the fact that Hydra is built on +RDF, which is a graph, it may happen that a related resource +(an object of the relation) may not be fully described in the +resource’s payload.

+

In several circumstances (i.e. payload terms defined in API documentation sa described in § 4.2 Documenting a Web API or IriTemplate expected as a related resource as described in Templated Links) client may +discover no additional statements describing it. These rules should +be considered by the client in following scenarios:

+
    +
  • +

    in case of an object expected to be a hypermedia resource does not have +all the necessary statements for which it is a subject, the client +SHOULD look in the API documentation for more details

    +
  • +

    in case the mentioned object, after consulting +an API documentation, still does not have +all the necessary statements for which it is a subject and both +mentioned object’s Url and Url of the initially obtained resource +has the same scheme and authority (by means of [RFC3986] sections 3.1 and 3.2), the client SHOULD dereference that URL. +If the resource does not have the same scheme and authority the client +MAY chose to dereference it (for example if the resource originates +from another API well-known to the client)

    +
  • +

    in case the mentioned object still does not have all the necessary +statements for which it is a subject (i.e. dereferencing it failed +or statements are missing), the client SHOULD either ignore the whole +statement (i.e. for display purposes) or throw an exception +(i.e. an IriTemplate is about to be resolved and dereferenced)

    +
+

Example of each of the situations are as follows:

+
+ +
EXAMPLE: IriTemplate details extraction
+
HTTP/1.1 200 OKContent-Type: application/ld+jsonLink: <http://api.example.com/doc/>; rel="http://www.w3.org/ns/hydra/core#apiDocumentation"{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@graph": [{        "@id": "http://api.example.com/attachments",        "@type": "hydra:Collection",        "api:attachmentByIssue": "api:AttachmentByIssueTemplate"    }, {        "@id": "http://api.example.com/issues",        "@type": "hydra:Collection",        "api:issueByName": "api:IssueByNameTemplate"    }}
+
HTTP/1.1 200 OKContent-Type: application/ld+json{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@graph": [{        "@id": "api:AttachmentByIssueTemplate",        "@type": "hydra:IriTemplate",        "template": "http://api.example.com/attachments/{issue}",        ...    }]}
+
+

where:

+
    +
  • +

    resource http://api.example.com/attachments should have +an IriTemplate available as there is a complete definition +of the template available at http://api.example.com/doc/

    +
  • +

    resource http://api.example.com/issues should not have +an IRI template exposed as there are no additional details available, +neither in the initial resources' payload nor in the API documentation

    +
+

Note: Keep in mind that any resource described by any hypermedia control +may fail at runtime due to various reasons. Operation details +such as returns or possibleStatus may also vary at runtime, +which means client SHOULD always verify received payloads at runtime.

+

4.2. Documenting a Web API

+

In Web APIs, most representations are typically very similar. +Furthermore, resources often support the same operations. It thus +makes sense, to collect this information in a central documentation. +Traditionally, this has been done in natural language which forces +developers to hardcode that knowledge into their clients. Hydra +addresses this issue by making the documentation completely +machine-processable. The fact that all definitions can be identified +by URLs enables reuse at unprecedented granularity.

+

Hydra’s ApiDocumentation class builds the foundation for +the description of a Web API. As shown in the following example, +Hydra describes an API by giving it a title, a short description, and +documenting its main entry point. Furthermore, the classes known to +be supported by the Web API and additional information about status +codes that might be returned can be documented. This information +may be used to automatically generate documentations in natural +language.

+
+ +
EXAMPLE: The overall structure of a Hydra API documentation
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/doc/",    "@type": "ApiDocumentation",    "title": "The name of the API",    "description": "A short description of the API",    "entrypoint": "URL of the API’s main entry point",    "supportedClass": [        // "... Classes known to be supported by the Web API ..."    ],    "possibleStatus": [        // "... Statuses that should be expected and handled properly ..."    ]}
+
+

In Linked Data, properties are, just as everything else, identified +by IRIs and thus have global scope which implies that they have +independent semantics. In contrast, properties in data models as +used in common programming languages are class-dependent. Their +semantics depend on the class they belong to. In data models classes +are typically described by the properties they expose whereas in +Linked Data properties define to which classes they belong. If no +class is specified, it is assumed that a property may apply to every +class.

+

These differences have interesting consequences. For example, the +commonly asked question of which properties can be applied to an +instance of a specific class can typically not be answered for +Linked Data. Strictly speaking, any property which is not explicitly +forbidden could be applied. This stems from the fact that Linked Data +works under an open-world assumption whereas data models used by +programmers typically work under a closed-world assumption. The +difference is that when a closed world is assumed, everything that +is not known to be true is false or vice-versa. With an open-world +assumption the failure to derive a fact does not automatically imply +the opposite; it embraces the fact that the knowledge is incomplete.

+

Since Hydra may use classes to describe the information expected or +returned by an operation, it also defines a concept to describe the +properties known to be supported by a class. The following example +illustrates this feature. Instead of referencing properties directly, supportedProperty references an intermediate data structure, +namely instances of the SupportedProperty class. This makes +it possible to define whether a specific property is required or +whether it is read-only or write-only depending on the class it is +associated with.

+
+ +
EXAMPLE: Defining a class and documenting its supported properties
+
{    "@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?"            "writable": true // "Can the client change the property’s value?"        }    ]}
+
+

All instances of a specific class typically support the same operations. +Hydra therefore features a supportedOperation property which defines +the operations supported by all instances of a class.

+
+ +
EXAMPLE: Defining a class and documenting its supported operations
+
{    "@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 ..."    ],    "supportedOperation": [        // "... Operations known to be supported by instances of the class ..."    ]}
+
+

The same feature can be used to describe the operations supported +by values of a Link property. This is often helpful when +certain operations depend on the permissions of the current user. It +makes it, e.g., possible to show a "delete" link only if the current +user has the permission to delete the resource. Otherwise, the link +would simply be hidden in the representation.

+

Example shown below describes the operation’s expected and returned +value as a dereferencable resource (an RDF resource of a given class), +but the vocabulary is not limited to only those originating +from RDF and is enabled to other types of resources. +Please note that in case of multiple either returned or expected types +provided, client SHOULD assume the set includes any of the types, +but not limited to those types and client SHOULD interpret a received +payload at runtime for possible discrepancies.

+
+ +
EXAMPLE: Documenting the supported operations of link properties
+
{    "@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": "Operation",            "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 ..."            ]        }    ]}
+
+

Note: It is worth to mention that Hydra comes with a notion +of a dereferenceability promise, which means that resources marked +with a Resource class can be safely dereferenced by a client. +Unfortunately, the way how the Word Wide Web works it is impossible to +guarantee that the resource finally will be obtained.

+

In addition to expected/returned resources, +it is also possible to express similar features for headers with returnsHeader and expectsHeader predicates which provides +a simple set of header names. Client SHOULD apply respective header +semantics when creating or receiving a request natural for the protocol in use.

+
+ +
EXAMPLE: Making a use of a returned header
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/doc/#comments",    "@type": "Link",    "supportedOperation": [        {            "@type": "Operation",            "method": "POST",            "expects": "http://api.example.com/doc/#Comment",            "returns": "http://api.example.com/doc/#Comment",            "returnsHeader": [                "Content-Type",                "Content-Length"],            "expectsHeader": [                "Authorization"            ]        }    ]}
+
+

The example above enable an HTTP client to prepare a proper cross-site +pre-flight request, so the server exposes enlisted headers for the client. +The client is also aware of the user authentication requirement necessary +for the operation invocation.

+

For more complex scenarios it is also possible to expand selected header +specification with both name and possible values, i.e. when defining +expected Content-Type values of resources that can be uploaded. +In case multiple possible values are provided, client SHOULD assume +that the set includes any of the values, but not limited to those values. +In order to change that default behavior it is possible to use closedSet predicate on the header specification indicating that the set of provided +values is, well, closed and no other values are available. In both cases +the client SHOULD interpret a received payload at runtime for possible +discrepancies.

+
+ +
EXAMPLE: Making a use of a expected header values
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/doc/#comments",    "@type": "Link",    "supportedOperation": [        {            "@type": "Operation",            "method": "POST",            "expects": "http://api.example.com/doc/#Upload",            "returns": "http://api.example.com/doc/#Comment",            "returnsHeader": [                {                    "headerName": "Content-Type",                    "possibleValue": ["text/turtle", "application/ld+json"]                }                "Content-Length"            ],            "expectsHeader": [                "Authorization",                {                    "headerName": "Content-Type",                    "possibleValue": ["image/gif", "image/png"]                }            ]        }    ]}
+
+

To wrap up everything altogether, it is also possible to attach atomic +operations supported by, well, supported property itself. This might +come in handy for scenarios, when resource can be partially modified. +It can be achieved with two approaches, both having advantages and +disadvantages.

+

First approach would involve adding a supportedOperation to the +intermediate structure of SupportedProperty. +This way prevents from leaking API specific features from the API itself +to i.e. externally defined properties. Data aggregators won’t assume that +each instance with a given property could have such an operation.

+

Another approach would require the API to elevate a specific property +to Link, which can accept a supportedOperation. This +is more intuitive in APIs operating with internally used vocabularies +where assumption that every instance with that very specific property +has the operation attached available.

+

Direct usage of supportedOperation on rdf:Property without elevating it to the Link SHOULD NOT be implemented as clients +may not discover such a construct correctly.

+

Note: These are the simple example scenarios and possible usages are not +limited to those described above.

+

Due to the fact an ApiDocumentation as all other resources may fail +at runtime, it is important to take countermeasures. A simple strategy +to try to recover from such a situation would be to reload +the ApiDocumentation and redo all pre-computations that were +based on the ApiDocumentation (or at least those that lead +to the current failure). Another, simpler approach would require +an application to show an error message with option to return +to a previous or home screen.

+

Hydra also allows enriching both ApiDocumentation and +hypermedia controls with human-readable descriptions by applying title and description (as shown in the examples above). +The former states a name of such a decorated element that could +be displayed as a label. The latter provides its description +to be presented i.e. as a hint.

+

Aforementioned title and description SHOULD take precedence +over standard rdfs:label and rdfs:comment.

+

There is one more feature related to how Linked Data works. Consider the +example below written in turtle syntax:

+
+ +
EXAMPLE: RDF as a graph
+
# An example API documentation itself with all the standard bits@base <http://some.app/> .@prefix api: <http://some.api/> .@prefix ex: <http://ontology.example/> .@prefix hydra: <http://www.w3.org/ns/hydra/core> .@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .<api>  a hydra:ApiDocumentation ;  hydra:supportedClass api:ClassOne, api:ClassTwo .# Anything elseex:SomeType a rdfs:Class .
+
+

...and how it could be transformed with JSON-LD framing process:

+
+ +
EXAMPLE: RDF as a graph continued
+
{    "@context": { ... },    "@graph": [        {            "@id": "http://some.app/api",            "@type": "hydra:ApiDocumentation",            "hydra:supportedClass": [                {                    "@id": "api:ClassTwo"                },                {                    "@id": "api:ClassOne"                }            ]        }    ]}
+
+

As you can see, additional details about ex:SomeType went +missing, while this shouldn’t happen. The fact that the IRI mentioned +is an rdfs:Class may be meaningful for a correct interpretation +of the received payload and this is a sole reason of why a Client +SHOULD NOT disregard other parts of the payload that are not directly +related to the API documentation or other hypermedia controls.

+

4.3. Discovering a Hydra-powered Web API

+

The first step when trying to access a Web API is to find an entry +point. Typically, this is done by looking for a documentation on the +API publisher’s homepage. Hydra enables the API’s main entry point +to be discovered automatically if the API publisher marks his +responses with a special HTTP Link Header as defined in [RFC8288]. +A Hydra client would look for a Link Header with a relation type http://www.w3.org/ns/hydra/core#apiDocumentation (this is +the IRI identifying the apiDocumentation property).

+

In the following example, a Hydra client simply accesses the +homepage of an API publisher (http://www.example.com/) +to find the entry point of its API. A client may use an HTTP GET or +HEAD request. The difference between the two is that the former may +return a message-body in the response whereas the latter will not; +otherwise they are identical.

+
+ +
EXAMPLE: Discovering Hydra API documentation documents
+
HEAD / HTTP/1.1Host: www.example.com
+
HTTP/1.1 200 OK...Content-Type: text/html; charset=utf-8Link: <http://api.example.com/doc/>; rel="http://www.w3.org/ns/hydra/core#apiDocumentation"
+
+

The response in the example above contains an HTTP Link Header +pointing to http://api.example.com/doc/. Retrieving that resource, +the client would obtain a Hydra API documentation defining the API’s main entry point:

+
+ +
EXAMPLE: Retrieving a Hydra API documentation to obtain the main entry point
+
GET /doc/ HTTP/1.1Host: api.example.comAccept: application/ld+json
+
HTTP/1.1 200 OK...Content-Type: application/ld+json{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/doc/",    "title": "The example.com API",    "entrypoint": "http://api.example.com/",    ...}
+
+

Note: Please note that in some cases the entry point will already be +known to the client. Thus, the discovery of the API documentation +using HTTP Link Headers may not be necessary as the concepts +used in responses from the API will dereference to their documentation.

+

In another scenario the ApiDocumentation would be discovered from +a bookmarked resource’s representation. +The API implementation SHOULD emit the HTTP Link header on every API response, making the ApiDocumentation (and entry +points it defined) discoverable all the time.

+
+ +
EXAMPLE: Retrieving a Hydra API documentation from another API response
+
GET /api/items HTTP/1.1Host: api.example.comAccept: application/ld+json
+
HTTP/1.1 200 OK...Content-Type: application/ld+jsonLink: <http://api.example.com/doc/>; rel="http://www.w3.org/ns/hydra/core#apiDocumentation"{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api/items",    "title": "Items collection",    ...}
+
+

4.4. Api versions

+

It is common to provide a separate API address after a breaking changes +update. This prevents current clients not to get broken as these may not +support these changes.

+

With hypermedia provided in each response payload, it may be unnecessary +to provide such an alternative API. This is due to fact the client follows +what the server provides and with proper margin for errors implemented +within that client, even breaking changes can be published on the fly.

+

Still, Hydra does neither have any special support for API versions, nor +prevents them. It’s fully an implementers decision on if and how +to provide the API features.

+

5. Advanced Concepts

+

5.1. Collections

+

In many situations, it makes sense to expose resources that reference +a set of somehow related resources. Results of a search query or +entries of an address book are just two examples. To simplify such +use cases, Hydra defines the two classes Collection and PartialCollectionView.

+

A Collection can be used to reference a set of resources +as follows:

+
+ +
EXAMPLE: Referencing related resources using a Hydra Collection
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/an-issue/comments",    "@type": "Collection",    "totalItems": 4980,    "member" : [        {            "@id": "/comments/429"        },        {            "@id": "/comments/781",            "title": "Properties may be embedded directly in the collection"        },        ...    ]}
+
+

As shown in the example above, member items can either consist of +solely a link or also include some properties. In some cases embedding +member properties directly in the collection is beneficial as it may +reduce the number of HTTP requests necessary to get enough information +to process the result.

+

Since collections may become very large, Web APIs often chose to +split a collection into multiple pages. In Hydra, that can be achieved +with a PartialCollectionView. It describes a specific +view on the collection which represents only a subset of the collection’s +members. A PartialCollectionView may contain links to the first, next, previous, and last PartialCollectionView which allows a client to find all members +of a Collection.

+
+ +
EXAMPLE: A Hydra PartialCollectionView splits a collection into multiple views
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/an-issue/comments",    "@type": "Collection",    "totalItems": 4980,    "member": [        // "... a subset of the members of the Collection ..."    ],    "view": {        "@id": "http://api.example.com/an-issue/comments?page=3",        "@type": "PartialCollectionView",        "first": "/an-issue/comments?page=1",        "previous": "/an-issue/comments?page=2",        "next": "/an-issue/comments?page=4",        "last": "/an-issue/comments?page=498"    }}
+
+

Note: It is worth to mention that all those links are optional, +and it is up to server whether to provide these links or not.

+

5.2. Member assertions

+

A memberAssertion (formerly manages) is a way to declare additional, +implicit statements about members of a collection. +Statements which may otherwise be missing from the respective member +resources inlined in a collection’s representation.

+
+ +
EXAMPLE: Member assertion describes relation with another resource
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/an-issue/comments",    "@type": "Collection",    "memberAssertion": {        "subject": "http://api.example.com/an-issue",        "property": "http://api.example.com/vocab#comment"    },    "member": [        {            "@id": "/comments/429"        }    ]}
+
+

In the above example, adding a memberAssertion node to the collection +instructs the client that every member of this collection is linked +to the subject by the property. It could be written as a SPARQL +triple pattern below, where ?m would be substituted by each member +of the collection.

+
<http://api.example.com/an-issue> <http://api.example.com/vocab#comment> ?m
+

A memberAssertion MUST use two and only two of the subject, property and object predicates. The memberAssertion predicate +MAY have more than one such blocks, each expressing different relations +between the collection members and other resources.

+

Note: It’s important to point out that the subject, property and object predicates are defined within the Hydra namespace +and are not rdfs terms.

+

It is also possible to use memberAssertion predicate on the +API documentation level, by attaching this predicate to subclasses +of the Collection, like in the example below. Clients would +understand that all members of collections which are instances +of api:UserCollections would in fact have rdf:type api:User.

+
+ +
EXAMPLE: Member assertion block describes strongly typed collection
+
{    "@context": [        "http://www.w3.org/ns/hydra/context.jsonld",        { "api": "http://api.example.com/api/documentation#" }    ],    "@id": "http://api.example.com/api/documentation",    "@type": "ApiDocumentation",    "supportedClass": ["api:User", "api:UserCollection"],    "api:UserCollection": {        "subClassOf": "Collection",        "memberAssertion": {            "property": "rdf:type",            "object": "api:User"        },    }}
+
+

It is worth to mention that a strongly typed collection instance can have +its own member assertions. In such a scenario, both API documentation level and instance +level assertions should be combined as neither makes the other obsolete.

+

More complex scenario would involve a class hierarchy, in which each class +can carry additional member assertions compared to it’s base class. +To discover all available member assertion blocks client SHOULD traverse +whole class hierarchy to gather all the member assertions. In order +to take such a burden from clients it is strongly recommended providing +all member assertion blocks to be provided on each class level including +its base class blocks, so the client does not have to perform +this traversing behavior.

+ +

Sometimes, it is impossible for a server to construct a URL because +the URL depends on information only known by the client. A typical +use case are URLs which enable a client to query the server. In such +a case, the server cannot construct the URL because it does not know +the query the client is interested in. What the server can do however, +is to give the client a template to construct such a URL at runtime. +In Hydra, the IriTemplate class is used to do so.

+

An IriTemplate consists of a template literal and a set +of mappings. Each IriTemplateMapping maps a variable used in the template to a property and may +optionally specify whether that variable is required or not. +The syntax of the template literal is specified by its datatype and +defaults to the [RFC6570] URI Template syntax, which can be +explicitly indicated by Rfc6570Template.

+
+ +
EXAMPLE: Description of an IRI Template
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@type": "IriTemplate",    "template": "http://api.example.com/issues{?q}",    "variableRepresentation": "hydra:BasicRepresentation",    "mapping": [        {            "@type": "IriTemplateMapping",            "variable": "q",            "property": "hydra:freetextQuery",            "required": true        }    ]}
+
+

The example above maps the variable q to Hydra’s freetextQuery property and marks it as required. As its name suggests, +the freetextQuery property can be used for free text queries.

+

A template syntax only details how to fill out simple string values, +but not how to derive such string values from typed values, +language-tagged strings, or IRIs. Hydra addresses this by +specifying how such values are to be serialized as strings. The +serialization of an IriTemplate’s variables can be described +by setting the variableRepresentation property to BasicRepresentation or ExplicitRepresentation. The BasicRepresentation represents values by their lexical form. It +omits type and language information and does not differentiate between +IRIs and literals. The ExplicitRepresentation, on the other +hand, includes type and language information and differentiates +between IRIs and literals by serializing values as follows:

+
    +
  • +

    IRIs are represented as-is

    +
  • +

    literals, i.e., (typed) values and language-tagged strings are +represented by their lexical form, surrounded by a single pair of +doubles quotes (")

    +
  • +

    if a literal has a language, a single @ symbol is +appended after the double-quoted lexical form, followed by a +non-empty [BCP47] language code

    +
  • +

    if a literal has a type, two caret symbols (^^) are appended +after the double-quoted literal, followed by the full datatype IRI

    +
+

In both representations characters MUST NOT be escaped. In case the +representation format is not explicitly described, clients SHOULD +use the BasicRepresentation by default.

+

Warning: Although ExplicitRepresentation use of @ and ^^ is similar, it is not the same as the [Turtle] representation for literals. Turtle literals require escaping +of special characters, surround datatype IRIs with angular brackets +(< and >), and also allow single quotes (') to indicate literals. +The ExplicitRepresentation values must not be escaped, +IRIs must not be surrounded by any character, and only double quotes +can indicate literals.

+

Below are some example values serialized in the different +representations as well as the result of expanding the IRI template http://example.com/find/{value} with the respective value.

+ +

Similar to how Hydra’s Link class allows the definition of +properties that represent hyperlinks as described in § 4.1 Adding Affordances to Representations, the TemplatedLink class +allows the definition of properties whose value are IRI templates. +Hydra predefines one such property, namely the search property which +can be used to document available search interfaces.

+
+ +
EXAMPLE: The definition of Hydra’s search property (extract)
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "hydra:search",    "@type": "hydra:TemplatedLink"}
+
+

IRI expansion should be performed with respect to the specification +behind the IRI template type ([RFC6570] by default), and the product +of this process SHOULD be an IRI. When the produced IRI is relative, +the client SHOULD stick to [RFC3986] sections 5.1.3 and 5.1.4 +to be compatible with most RDF serializations that support relative IRIs. +Still, it may be preferred to use another base URI for the expansion +process, which makes the resolveRelativeUsing term useful. It allows +to switch the IRI template expansion algorithm, so the base URI +is established using current link context, which is a subject +of the relation pointing to an IriTemplate instance. In case +that subject is a relative URI, default behavior SHOULD be used as fallback.

+

The example below allows to make the product of an IRI template +expansion relative to the http://api.example.com/an-issue/ resource +by using it as its base URI, which further enables the some:operation to be moved to i.e. API documentation level rather +to inline it.

+
+ +
EXAMPLE: Custom base Uri resolution for an Iri template
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/an-issue/",    "@type": "Collection",    "some:operation": {        "@type": "IriTemplate",        "template": "{id}",        "resolveRelativeUsing": "LinkContext",        "variable": "id",        "mapping": {...}    }}
+
+

When constructed, the IRI would effectively become similar +to http://api.example.com/an-issue/1234, with the relative part {id} appended to the link context URL.

+

5.4. IRI template operations

+

There are circumstances in which client would like to perform an operation +not knowing the final IRI of the resource to be called. This case +is especially in force when working with collections - client may want +to add a new collection member, or it may need to provide more details +while searching with other protocol’s method (i.e. POST instead of GET +in case of an HTTP).

+

This is achievable by attaching a supportedOperation to the property +that connects a subject of that relation with its IriTemplate as described in the previous part of this document. Please note that +client is still allowed to use the defined link and custom operation’s +method is optional.

+
+ +
EXAMPLE: Operation with IRI template
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api-documentation",    "@type": "ApiDocumentation",    "api:search": {        "@type": "Link",        "rdfs:subClassOf": "search",        "supportedOperation": {            "@type": "SupportedOperation",            "method": "POST"        }    }}
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/issues",    "@type": "Collection",    "api:search": {        "@type": "IriTemplate",        "template": "/issues?search={name}",        "mapping": { ... }    }}
+
+

The example above allows client to either invoke an HTTP GET or POST +call on http://api.example.com/issues?search=search_string resource.

+
+ +
EXAMPLE: Operation with IRI template without link option
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api-documentation",    "@type": "ApiDocumentation",    "api:find": {        "supportedOperation": {            "@type": "SupportedOperation",            "method": "POST"        }    }}
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/issues",    "@type": "Collection",    "api:search": {        "@type": "IriTemplate",        "template": "/issues?find={name}",        "mapping": {...}    }}
+
+

The example above allows client to invoke only an HTTP POST +call on http://api.example.com/issues?find=search_string resource as +the described relation of find is not a Link.

+

5.5. Supported property data source

+

There are circumstances in which an API would like to inform a client on +when to obtain values to feed data structures with details. Having all the +necessary components like supported property, collection and IRI templates, +it is possible to drive the client and direct it with links and operations +to the data sources.

+

It is doable by attaching either a collection or search predicate to instance of supportedProperty or to property. +In such case client SHOULD assume that the relation leads to +the collection of values compatible with the supported property’s range +and can be used to feed data structures with the supported property. +It is recommended (but not mandatory) to use freetextQuery variable mapping in case of the search predicate as it has a +well-defined semantics and takes the burden of interpretation from +the client.

+

While it is possible to provide such links in both API documentation and within the received payload, +client SHOULD use the latter link first if applicable. +This is due to the fact the server may want to put additional +context to narrow the collection of viable values. Redefinition does not +make the more general one obsolete though and can be used as a fallback.

+
+ +
EXAMPLE: Supported property data source
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@type": "ApiDocumentation",    "supportedClass": {        "@id": "schema:Event",        "supportedProperty": {            "property": "schema:actor",            "search": {                "template": "/api/user{?search}",                "mapping": {                    "variable": "search",                    "property": "freetextQuery"                }            }        }    },    ...}
+
+

The example above instructs a client that every resource of type schema:Event can have a relation of schema:actor, the objects +of which the client can obtain using the search link provided.

+

5.6. Description of HTTP Status Codes and Errors

+

In case of the HTTP protocol, status codes have well-defined semantics +and can be used to signal the outcome of an operation. Unfortunately, +however, HTTP status codes by themselves are often not specific enough, +making it difficult to understand the real cause of an error. For instance, +a 429 Too Many Requests response is rarely informative enough by itself. +To address this issue, Hydra defines a Status class which allows +additional information to be associated with the HTTP status code.

+
+ +
EXAMPLE: Associating additional information to an HTTP status code
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@type": "Status",    "statusCode": 429,    "title": "Too Many Requests",    "description": "A maximum of 500 requests per hour and user is allowed.",    ...}
+
+

An ApiDocumentation or an Operation may document the +status codes that might be returned by the server using the possibleStatus property as described in § 4.2 Documenting a Web API. +This allows a developer to understand what to expect when invoking +an operation. It has, however, not to be considered as an extensive +list of all potentially returned status codes; it is merely a hint. +Developers should expect to encounter other HTTP status codes as well.

+

A server may also return a Status directly in a response. +When doing so, it often makes sense to subclass the Status to make its semantics more explicit. Hydra defines just one such subclass, +namely the Error class. This provides an extensible framework +to communicate error details to a client.

+

Furthermore, a Status or Error returned by the server can also +be given an identifier. When dereferenced, the Error resource +can provide more detailed information or possible ways to resolve +the problem, if applicable.

+

Finally, the server SHOULD provide error descriptions using an [RFC7807] standard by using an application/problem+json response. When doing so, +the server also MUST provide an additional header pointing to either +the built-in Hydra http://www.w3.org/ns/hydra/error context +or any JSON-LD context that maps the terms type, title, detail, status and instance the same way as the standard one.

+
+ +
EXAMPLE: RFC-7807 compatible error description
+
HTTP/1.1 400 Bad RequestContent-Type: application/problem+jsonLink: <http://www.w3.org/ns/hydra/error>; rel="http://www.w3.org/ns/json-ld#context"{    "type": "https://example.com/probs/out-of-credit",    "@type": "http://www.w3.org/ns/hydra/core#Error",    "title": "You do not have enough credit.",    "detail": "Your current balance is 30, but that costs 50.",    "instance": "/account/12345/msgs/abc",    "balance": 30,    "accounts": [        "/account/12345",        "/account/67890"    ]}
+
+

While the built-in context makes the response fully compatible with +the mentioned specification, properties not defined in the standard +Hydra’s error context won’t be visible for Hydra aware processors. +To overcome this, it is possible to declare a custom context pointed +the same way, that would combine standard Hydra’s standard error context +and an additional JSON-LD context with either the @vocab or custom +property mappings telling the processor on how to interpret those custom +error properties.

+

Resources provided may have an additional hint pointing to an Error type like in the example above, but it is not mandatory to do so as all +resources described with application/problem+json are considered Error.

+

Note: It is worth to mention that it may happen (i.e. due to proxy behavior) +the value of the status property will differ to the one received +from the protocol layer.

+
+ +
EXAMPLE: Non RFC-7807 compliant error description using raw Hydra JSON-LD representation
+
HTTP/1.1 400 Bad RequestContent-Type: application/ld+json{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@type": "Error",    "@id": "http://api.example.com/error-details/1234",    "title": "An error occurred",    "description": "Typically, a specialization of this class is used in practice.",    ...}
+
+

5.7. Client initiated pagination

+

There are situations when a client would like to provide a specific +collection limitations, i.e. by providing query-language like member +offset and limit, or some specific page index and number of members +per page. This is doable with offset/limit or pageIndex/limit predicates.

+

With those, it is possible to bind a template variables mapped +with externally obtained values (i.e. user interaction) the same way +as with other mappings.

+

While the predicates enlisted above accepts non-negative integer +numbers, there is also a possibility of providing a custom page +reference expressed via pageReference predicate. It is possible +to provide a custom page identifier (i.e. a GUID or a letter) +instead of a number.

+

5.8. Extensions

+

While Hydra Core Vocabulary allows addressing many usage scenarios, +not every aspect of API behavior can be covered. This +applies especially to querying, resource projection or data structure +description. This is due to fact that Hydra is meant to be as light +as possible forcing to drop some features out of its scope.

+

That is why there is a possibility of hinting a client on what kind +of extensions may be found or used in the received payloads. +After discovering an extension predicate in the API documentation, client can assume additional +details are available described with complementary vocabularies.

+
+ +
EXAMPLE: Hydra client extension usage
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/doc/",    "@type": "ApiDocumentation",    "title": "The name of the API",    "description": "A short description of the API",    "entrypoint": "URL of the API’s main entry point",    "extension": "http://www.w3.org/ns/shacl#",    ...}
+
+

It is up to the used vocabulary to define how these additional details +should be interpreted. In case client does not recognize these extensions, +additional details should be ignored and base Hydra interpretation +should be in force.

+

Server SHOULD NOT use extensions to add statements that are in +contradiction to base Hydra interpretation, so the client is not confused. +Server SHOULD also keep multiple extensions describing adequate +knowledge in line regarding their description (i.e. data structure +descriptions in various vocabularies should not cause differences).

+

Client can express its preferences through the Prefer HTTP header +by pointing the preferred extensions via IRIs as on the example below. +The client SHOULD use the Prefer HTTP header [RFC7240] with +the hydra.extension preference as an iri attribute having +the IRI of the extension as value to hint the server about the extension +it supports. Multiple preferences can be expressed by providing multiple Prefer header values.

+
+ +
EXAMPLE: Hydra client extension preference
+
GET http://api.example.com/api/people HTTP/1.1Prefer: hydra.extension; iri="http://schema.org/"
+
+

Server MUST implement Prefer header handling according to +the [RFC7240] and implementers should proceed with caution.

+

6. Classes

+

6.1. hydra:ApiDocumentation

+ + + + + +
Name: + ApiDocumentation +
Summary: + The Hydra API documentation class. +
Sub-class of: + Resource +
+
+ +
EXAMPLE: hydra:ApiDescription
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api?documentation",    "@type": "ApiDocumentation",    "entrypoint": "http://api.example.com/api",    "extension": "https://w3id.org/hydra/extension#shacl",    "supportedClass": [        {            "@id": "http://api.example.com/vocab#User",            "title": "User",            "description": "Describes a system user.",            "supportedOperation": [                {                    "method": "PUT",                    "title": "Create new user",                    "description": "Creates a brand new user.",                    "expects": "http://api.example.com/vocab#User",                    "returns": "http://api.example.com/vocab#User",                    "returnsHeader": [                        {                            "headerName": "Content-Type",                            "possibleValue": ["text/turtle", "application/ld+json"],                            "closedSet": true                        }                        "Content-Length"                    ],                    "expectsHeader": [                        "Authorization",                        {                            "headerName": "Content-Type",                            "possibleValue": ["image/gif", "image/png"],                            "closedSet": true                        }                    ]                }            ],            "supportedProperty": [                {                    "property": "http://api.example.com/vocab#login",                    "writable": true,                    "readable": true,                    "required": true                }            ]        }    ]}
+
+

6.2. hydra:BaseUriSource

+ + + + + + +
Name: + BaseUriSource +
Summary: + Provides a base abstract for base Uri source + for Iri template resolution. +
Sub-class of: + Resource +
Named instances: + Rfc3986, LinkContext +
+

6.3. hydra:Class

+ + + + + +
Name: + Class +
Summary: + The class of Hydra classes. +
Sub-class of: + rdfs:Class +
+

6.4. hydra:Collection

+ + + + + +
Name: + Collection +
Summary: + A collection holding references to a number of related resources. +
Sub-class of: + Resource +
+
+ +
EXAMPLE: hydra:Collection
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api/posts",    "@type": "Collection",    "view": {        "@id": "http://api.example.com/api/posts?skip=10",        "@type": "PartialCollectionView",        "first": "http://api.example.com/api/posts",        "last": "http://api.example.com/api/posts?skip=100",        "previous": "http://api.example.com/api/posts",        "next": "http://api.example.com/api/posts?skip=20",        "totalItems": 10,    },    "totalItems": 100,    "member": [        { "@id": "http://api.example.com/api/posts/10" },        { "@id": "http://api.example.com/api/posts/11" },        { "@id": "http://api.example.com/api/posts/12" },        { "@id": "http://api.example.com/api/posts/13" },        { "@id": "http://api.example.com/api/posts/14" },        { "@id": "http://api.example.com/api/posts/15" },        { "@id": "http://api.example.com/api/posts/16" },        { "@id": "http://api.example.com/api/posts/17" },        { "@id": "http://api.example.com/api/posts/18" },        { "@id": "http://api.example.com/api/posts/19" }    ],    "search": {        "template": "/api/posts{?search,limit,offset}",        "resolveRelativeUsing": "hydra:Rfc3986",        "mapping": [            {                "variable": "search",                "property": "hydra:freetextQuery",                "required": true,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "limit",                "property": "hydra:limit",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "offset",                "property": "hydra:offset",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            }        ]    }}
+
+

6.5. hydra:Error

+ + + + + +
Name: + Error +
Summary: + A runtime error, used to report information beyond the returned + status code. +
Sub-class of: + Status +
+
+ +
EXAMPLE: hydra:Error
+
HTTP/1.1 400 Bad requestContent-Type: application/problem+jsonLink: <http://www.w3.org/ns/hydra/error>; rel="http://www.w3.org/ns/json-ld#context"{"type": "https://api.example.com/vocab#NullReferenceException","@type": "http://www.w3.org/ns/hydra/core#Error","title": "The request cannot be processed.","detail": "Provided value cannot be 'null'.","instance": "http://api.example.com/api/posts","status": 404}
+
+

6.6. hydra:HeaderSpecification

+ + + + + +
Name: + HeaderSpecification +
Summary: + Specifies a possible either expected or returned header values. +
Sub-class of: + Resource +
+
+ +
EXAMPLE: hydra:HeaderSpecification
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api?documentation",    "@type": "ApiDocumentation",    "entrypoint": "http://api.example.com/api",    "extension": "https://w3id.org/hydra/extension#shacl",    "supportedClass": [        {            "@id": "http://api.example.com/vocab#User",            "title": "User",            "description": "Describes a system user.",            "supportedOperation": [                {                    "method": "PUT",                    "title": "Create new user",                    "description": "Creates a brand new user.",                    "expects": "http://api.example.com/vocab#User",                    "returns": "http://api.example.com/vocab#User",                    "returnsHeader": [                        {                            "@type": "hydra:HeaderSpecification",                            "headerName": "Content-Type",                            "possibleValue": ["text/turtle", "application/ld+json"],                            "closedSet": true                        }                        "Content-Length"                    ],                    "expectsHeader": [                        "Authorization",                        {                            "@type": "hydra:HeaderSpecification",                            "headerName": "Content-Type",                            "possibleValue": ["image/gif", "image/png"],                            "closedSet": true                        }                    ]                }            ],            "supportedProperty": [                {                    "property": "http://api.example.com/vocab#login",                    "writable": true,                    "readable": true,                    "required": true                }            ]        }    ]}
+
+

6.7. hydra:IriTemplate

+ + + + +
Name: + IriTemplate +
Summary: + The class of IRI templates. +
+
+ +
EXAMPLE: hydra:IriTemplate
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api/posts",    "@type": "Collection",    "view": {        "@id": "http://api.example.com/api/posts?skip=10",        "@type": "PartialCollectionView",        "first": "http://api.example.com/api/posts",        "last": "http://api.example.com/api/posts?skip=100",        "previous": "http://api.example.com/api/posts",        "next": "http://api.example.com/api/posts?skip=20",        "totalItems": 10,    },    "totalItems": 100,    "member": [        { "@id": "http://api.example.com/api/posts/10" },        { "@id": "http://api.example.com/api/posts/11" },        { "@id": "http://api.example.com/api/posts/12" },        { "@id": "http://api.example.com/api/posts/13" },        { "@id": "http://api.example.com/api/posts/14" },        { "@id": "http://api.example.com/api/posts/15" },        { "@id": "http://api.example.com/api/posts/16" },        { "@id": "http://api.example.com/api/posts/17" },        { "@id": "http://api.example.com/api/posts/18" },        { "@id": "http://api.example.com/api/posts/19" }    ],    "search": {        "@type": "hydra:IriTemplate",        "template": "/api/posts{?search,limit,offset}",        "resolveRelativeUsing": "hydra:Rfc3986",        "mapping": [            {                "variable": "search",                "property": "hydra:freetextQuery",                "required": true,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "limit",                "property": "hydra:limit",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "offset",                "property": "hydra:offset",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            }        ]    }}
+
+

6.8. hydra:IriTemplateMapping

+ + + + +
Name: + IriTemplateMapping +
Summary: + A mapping from an IRI template variable to a property. +
+
+ +
EXAMPLE: hydra:IriTemplateMapping
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api/posts",    "@type": "Collection",    "view": {        "@id": "http://api.example.com/api/posts?skip=10",        "@type": "PartialCollectionView",        "first": "http://api.example.com/api/posts",        "last": "http://api.example.com/api/posts?skip=100",        "previous": "http://api.example.com/api/posts",        "next": "http://api.example.com/api/posts?skip=20",        "totalItems": 10,    },    "totalItems": 100,    "member": [        { "@id": "http://api.example.com/api/posts/10" },        { "@id": "http://api.example.com/api/posts/11" },        { "@id": "http://api.example.com/api/posts/12" },        { "@id": "http://api.example.com/api/posts/13" },        { "@id": "http://api.example.com/api/posts/14" },        { "@id": "http://api.example.com/api/posts/15" },        { "@id": "http://api.example.com/api/posts/16" },        { "@id": "http://api.example.com/api/posts/17" },        { "@id": "http://api.example.com/api/posts/18" },        { "@id": "http://api.example.com/api/posts/19" }    ],    "search": {        "@type": "hydra:IriTemplate",        "template": "/api/posts{?search,limit,offset}",        "resolveRelativeUsing": "hydra:Rfc3986",        "mapping": [            {                "@type": "hydra:IriTemplateMapping",                "variable": "search",                "property": "hydra:freetextQuery",                "required": true,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "@type": "hydra:IriTemplateMapping",                "variable": "limit",                "property": "hydra:limit",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "@type": "hydra:IriTemplateMapping",                "variable": "offset",                "property": "hydra:offset",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            }        ]    }}
+
+ + + + + + +
Name: + Link +
Summary: + The class of properties representing links. +
Sub-class of: + Resource, rdf:Property +
+
+ +
EXAMPLE: hydra:Link
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@graph": [        {            "@id": "http://api.example.com/api?documentation",            "@type": "ApiDocumentation",            "entrypoint": "http://api.example.com/api"        },        {            "@id": "http://api.example.com/vocab#comments",            "@type": "hydra:Link"        }    }}
+
+

6.10. hydra:Operation

+ + + + +
Name: + Operation +
Summary: + An operation. +
+
+ +
EXAMPLE: hydra:Operation
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api/posts/1",    "operation": [        {            "@type": "Operation",            "method": "DELETE",            "title": "Remove",            "description": "Removes post no. 1"        }    ]}
+
+

6.11. hydra:PartialCollectionView

+ + + + + +
Name: + PartialCollectionView +
Summary: + A PartialCollectionView describes a partial view of a Collection. + Multiple PartialCollectionViews can be connected with + the next/previous properties to allow a client to retrieve + all members of the collection. +
Sub-class of: + Resource +
+
+ +
EXAMPLE: hydra:PartialCollectionView
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api/posts",    "@type": "Collection",    "view": {        "@type": "PartialCollectionView",        "@id": "http://api.example.com/api/posts?skip=10",        "@type": "PartialCollectionView",        "first": "http://api.example.com/api/posts",        "last": "http://api.example.com/api/posts?skip=100",        "previous": "http://api.example.com/api/posts",        "next": "http://api.example.com/api/posts?skip=20",        "totalItems": 10,    },    "totalItems": 100,    "member": [        { "@id": "http://api.example.com/api/posts/10" },        { "@id": "http://api.example.com/api/posts/11" },        { "@id": "http://api.example.com/api/posts/12" },        { "@id": "http://api.example.com/api/posts/13" },        { "@id": "http://api.example.com/api/posts/14" },        { "@id": "http://api.example.com/api/posts/15" },        { "@id": "http://api.example.com/api/posts/16" },        { "@id": "http://api.example.com/api/posts/17" },        { "@id": "http://api.example.com/api/posts/18" },        { "@id": "http://api.example.com/api/posts/19" }    ],    "search": {        "template": "/api/posts{?search,limit,offset}",        "resolveRelativeUsing": "hydra:Rfc3986",        "mapping": [            {                "variable": "search",                "property": "hydra:freetextQuery",                "required": true,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "limit",                "property": "hydra:limit",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "offset",                "property": "hydra:offset",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            }        ]    }}
+
+

6.12. hydra:Resource

+ + + + +
Name: + Resource +
Summary: + The class of dereferenceable resources by means a client + can attempt to dereference; however, the received responses + should still be verified. +
+

6.13. hydra:Status

+ + + + +
Name: + Status +
Summary: + Additional information about a status code that might be returned. +
+
+ +
EXAMPLE: hydra:Status
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api/posts/1",    "operation": [        {            "method": "DELETE",            "title": "Remove",            "description": "Removes post no. 1",            "possibleStatus": [                {                    "@type": "Status",                    "statusCode": 303                }            ]        }    ]}
+
+

6.14. hydra:SupportedProperty

+ + + + +
Name: + SupportedProperty +
Summary: + A property known to be supported by a Hydra class. +
+
+ +
EXAMPLE: hydra:SupportedProperty
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api?documentation",    "@type": "ApiDocumentation",    "entrypoint": "http://api.example.com/api",    "extension": "https://w3id.org/hydra/extension#shacl",    "supportedClass": [        {            "@id": "http://api.example.com/vocab#User",            "title": "User",            "description": "Describes a system user.",            "supportedOperation": [                {                    "method": "PUT",                    "title": "Create new user",                    "description": "Creates a brand new user.",                    "expects": "http://api.example.com/vocab#User",                    "returns": "http://api.example.com/vocab#User",                    "returnsHeader": [                        {                            "headerName": "Content-Type",                            "possibleValue": ["text/turtle", "application/ld+json"],                            "closedSet": true                        }                        "Content-Length"                    ],                    "expectsHeader": [                        "Authorization",                        {                            "headerName": "Content-Type",                            "possibleValue": ["image/gif", "image/png"],                            "closedSet": true                        }                    ]                }            ],            "supportedProperty": [                {                    "@type": "SupportedProperty",                    "property": "http://api.example.com/vocab#login",                    "writable": true,                    "readable": true,                    "required": true                }            ]        }    ]}
+
+ + + + + + +
Name: + TemplatedLink +
Summary: + A templated link. +
Sub-class of: + Resource, rdf:Property +
+
+ +
EXAMPLE: hydra:TemplatedLink
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@graph": [        {            "@id": "http://api.example.com/api?documentation",            "@type": "ApiDocumentation",            "entrypoint": "http://api.example.com/api"        },        {            "@id": "http://api.example.com/vocab#comments",            "@type": "hydra:TemplatedLink"        }    }}
+
+

6.16. hydra:VariableRepresentation

+ + + + + +
Name: + VariableRepresentation +
Summary: + A representation specifies how to serialize variable + values into strings. +
Named instances: + BasicRepresentation, ExplicitRepresentation +
+

7. Properties

+

7.1. hydra:apiDocumentation

+ + + + + + +
Name: + apiDocumentation‎ +
Summary: + A link to the API documentation. +
Domain: + Resource +
Range: + ApiDocumentation +
+
+ +
EXAMPLE: hydra:apiDocumentation
+
HTTP/1.1 200 OKContent-Type: text/html; charset=utf-8Link: <http://api.example.com/doc/>; rel="http://www.w3.org/ns/hydra/core#apiDocumentation"
+
+

7.2. hydra:closedSet

+ + + + + + + +
Name: + closedSet +
Summary: + Determines whether the provided set of header values + is closed or not. +
Max cardinality: + 1 +
Domain: + HeaderSpecification +
Range: + xsd:boolean +
+
+ +
EXAMPLE: hydra:closedSet
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api?documentation",    "@type": "ApiDocumentation",    "entrypoint": "http://api.example.com/api",    "extension": "https://w3id.org/hydra/extension#shacl",    "supportedClass": [        {            "@id": "http://api.example.com/vocab#User",            "title": "User",            "description": "Describes a system user.",            "supportedOperation": [                {                    "method": "PUT",                    "title": "Create new user",                    "description": "Creates a brand new user.",                    "expects": "http://api.example.com/vocab#User",                    "returns": "http://api.example.com/vocab#User",                    "returnsHeader": [                        {                            "headerName": "Content-Type",                            "possibleValue": ["text/turtle", "application/ld+json"],                            "closedSet": true                        }                        "Content-Length"                    ],                    "expectsHeader": [                        "Authorization",                        {                            "headerName": "Content-Type",                            "possibleValue": ["image/gif", "image/png"],                            "closedSet": true                        }                    ]                }            ],            "supportedProperty": [                {                    "property": "http://api.example.com/vocab#login",                    "writable": true,                    "readable": true,                    "required": true                }            ]        }    ]}
+
+

7.3. hydra:collection

+ + + + + +
Name: + collection‎ +
Summary: + Collections somehow related to this resource. +
Range: + Collection +
+
+ +
EXAMPLE: hydra:collection
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api",    "collection": [        {            "@id": "http://api.example.com/api/posts",            "@type": "Collection",            "memberAssertion": [                {                    "property": "rdf:type",                    "object": "http://api.example.com/vocab#Post"                }            ]        }    ]}
+
+

7.4. hydra:description

+ + + + + + + +
Name: + description +
Summary: + A description. +
Max cardinality: + 1 +
Domain includes: + ApiDocumentation, Status, Class, SupportedProperty, Operation, Link, TemplatedLink +
Range: + xsd:string +
+
+ +
EXAMPLE: hydra:description
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api?documentation",    "@type": "ApiDocumentation",    "entrypoint": "http://api.example.com/api",    "extension": "https://w3id.org/hydra/extension#shacl",    "supportedClass": [        {            "@id": "http://api.example.com/vocab#User",            "title": "User",            "description": "Describes a system user.",            "supportedOperation": [                {                    "method": "PUT",                    "title": "Create new user",                    "description": "Creates a brand new user.",                    "expects": "http://api.example.com/vocab#User",                    "returns": "http://api.example.com/vocab#User",                    "returnsHeader": [                        {                            "headerName": "Content-Type",                            "possibleValue": ["text/turtle", "application/ld+json"],                            "closedSet": true                        }                        "Content-Length"                    ],                    "expectsHeader": [                        "Authorization",                        {                            "headerName": "Content-Type",                            "possibleValue": ["image/gif", "image/png"],                            "closedSet": true                        }                    ]                }            ],            "supportedProperty": [                {                    "property": "http://api.example.com/vocab#login",                    "writable": true,                    "readable": true,                    "required": true                }            ]        }    ]}
+
+

7.5. hydra:entrypoint

+ + + + + + + +
Name: + entrypoint +
Summary: + A link to main entry point of the Web API. +
Min cardinality: + 1 +
Domain: + ApiDocumentation +
Range: + Resource +
+
+ +
EXAMPLE: hydra:entrypoint
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api?documentation",    "@type": "ApiDocumentation",    "entrypoint": "http://api.example.com/api",    "extension": "https://w3id.org/hydra/extension#shacl",    "supportedClass": [        {            "@id": "http://api.example.com/vocab#User",            "title": "User",            "description": "Describes a system user.",            "supportedOperation": [                {                    "method": "PUT",                    "title": "Create new user",                    "description": "Creates a brand new user.",                    "expects": "http://api.example.com/vocab#User",                    "returns": "http://api.example.com/vocab#User",                    "returnsHeader": [                        {                            "headerName": "Content-Type",                            "possibleValue": ["text/turtle", "application/ld+json"],                            "closedSet": true                        }                        "Content-Length"                    ],                    "expectsHeader": [                        "Authorization",                        {                            "headerName": "Content-Type",                            "possibleValue": ["image/gif", "image/png"],                            "closedSet": true                        }                    ]                }            ],            "supportedProperty": [                {                    "property": "http://api.example.com/vocab#login",                    "writable": true,                    "readable": true,                    "required": true                }            ]        }    ]}
+
+

7.6. hydra:expects

+ + + + + + +
Name: + expects +
Summary: + The information expected by the Web API. +
Domain: + Operation +
Range includes: + rdfs:Resource, Resource, rdfs:Class, Class +
+
+ +
EXAMPLE: hydra:expects
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api?documentation",    "@type": "ApiDocumentation",    "entrypoint": "http://api.example.com/api",    "extension": "https://w3id.org/hydra/extension#shacl",    "supportedClass": [        {            "@id": "http://api.example.com/vocab#User",            "title": "User",            "description": "Describes a system user.",            "supportedOperation": [                {                    "method": "PUT",                    "title": "Create new user",                    "description": "Creates a brand new user.",                    "expects": "http://api.example.com/vocab#User",                    "returns": "http://api.example.com/vocab#User",                    "returnsHeader": [                        {                            "headerName": "Content-Type",                            "possibleValue": ["text/turtle", "application/ld+json"],                            "closedSet": true                        }                        "Content-Length"                    ],                    "expectsHeader": [                        "Authorization",                        {                            "headerName": "Content-Type",                            "possibleValue": ["image/gif", "image/png"],                            "closedSet": true                        }                    ]                }            ],            "supportedProperty": [                {                    "property": "http://api.example.com/vocab#login",                    "writable": true,                    "readable": true,                    "required": true                }            ]        }    ]}
+
+

7.7. hydra:expectsHeader

+ + + + + + +
Name: + expectsHeader +
Summary: + Specification of the header expected by the operation. +
Domain: + Operation +
Range includes: + xsd:string, HeaderSpecification +
+
+ +
EXAMPLE: hydra:expectsHeader
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api?documentation",    "@type": "ApiDocumentation",    "entrypoint": "http://api.example.com/api",    "extension": "https://w3id.org/hydra/extension#shacl",    "supportedClass": [        {            "@id": "http://api.example.com/vocab#User",            "title": "User",            "description": "Describes a system user.",            "supportedOperation": [                {                    "method": "PUT",                    "title": "Create new user",                    "description": "Creates a brand new user.",                    "expects": "http://api.example.com/vocab#User",                    "returns": "http://api.example.com/vocab#User",                    "returnsHeader": [                        {                            "headerName": "Content-Type",                            "possibleValue": ["text/turtle", "application/ld+json"],                            "closedSet": true                        }                        "Content-Length"                    ],                    "expectsHeader": [                        "Authorization",                        {                            "headerName": "Content-Type",                            "possibleValue": ["image/gif", "image/png"],                            "closedSet": true                        }                    ]                }            ],            "supportedProperty": [                {                    "property": "http://api.example.com/vocab#login",                    "writable": true,                    "readable": true,                    "required": true                }            ]        }    ]}
+
+

7.8. hydra:extension

+ + + + + +
Name: + extension +
Summary: + Hint on what kind of extensions are in use. +
Domain: + ApiDocumentation +
+
+ +
EXAMPLE: hydra:extension
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api?documentation",    "@type": "ApiDocumentation",    "entrypoint": "http://api.example.com/api",    "extension": "https://w3id.org/hydra/extension#shacl",    "supportedClass": [        {            "@id": "http://api.example.com/vocab#User",            "title": "User",            "description": "Describes a system user.",            "supportedOperation": [                {                    "method": "PUT",                    "title": "Create new user",                    "description": "Creates a brand new user.",                    "expects": "http://api.example.com/vocab#User",                    "returns": "http://api.example.com/vocab#User",                    "returnsHeader": [                        {                            "headerName": "Content-Type",                            "possibleValue": ["text/turtle", "application/ld+json"],                            "closedSet": true                        }                        "Content-Length"                    ],                    "expectsHeader": [                        "Authorization",                        {                            "headerName": "Content-Type",                            "possibleValue": ["image/gif", "image/png"],                            "closedSet": true                        }                    ]                }            ],            "supportedProperty": [                {                    "property": "http://api.example.com/vocab#login",                    "writable": true,                    "readable": true,                    "required": true                }            ]        }    ]}
+
+

7.9. hydra:first

+ + + + + + + +
Name: + first +
Summary: + The first resource of an interlinked set of resources. +
Max cardinality: + 1 +
Domain: + Resource +
Range: + Resource +
+
+ +
EXAMPLE: hydra:first
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api/posts",    "@type": "Collection",    "view": {        "@id": "http://api.example.com/api/posts?skip=10",        "@type": "PartialCollectionView",        "first": "http://api.example.com/api/posts",        "last": "http://api.example.com/api/posts?skip=100",        "previous": "http://api.example.com/api/posts",        "next": "http://api.example.com/api/posts?skip=20",        "totalItems": 10,    },    "totalItems": 100,    "member": [        { "@id": "http://api.example.com/api/posts/10" },        { "@id": "http://api.example.com/api/posts/11" },        { "@id": "http://api.example.com/api/posts/12" },        { "@id": "http://api.example.com/api/posts/13" },        { "@id": "http://api.example.com/api/posts/14" },        { "@id": "http://api.example.com/api/posts/15" },        { "@id": "http://api.example.com/api/posts/16" },        { "@id": "http://api.example.com/api/posts/17" },        { "@id": "http://api.example.com/api/posts/18" },        { "@id": "http://api.example.com/api/posts/19" }    ],    "search": {        "template": "/api/posts{?search,limit,offset}",        "resolveRelativeUsing": "hydra:Rfc3986",        "mapping": [            {                "variable": "search",                "property": "hydra:freetextQuery",                "required": true,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "limit",                "property": "hydra:limit",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "offset",                "property": "hydra:offset",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            }        ]    }}
+
+

7.10. hydra:freetextQuery

+ + + + + + +
Name: + freetextQuery +
Summary: + A property representing a freetext query. +
Domain: + Resource +
Range: + xsd:string +
+
+ +
EXAMPLE: hydra:freetextQuery
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api/posts",    "@type": "Collection",    "view": {        "@id": "http://api.example.com/api/posts?skip=10",        "@type": "PartialCollectionView",        "first": "http://api.example.com/api/posts",        "last": "http://api.example.com/api/posts?skip=100",        "previous": "http://api.example.com/api/posts",        "next": "http://api.example.com/api/posts?skip=20",        "totalItems": 10,    },    "totalItems": 100,    "member": [        { "@id": "http://api.example.com/api/posts/10" },        { "@id": "http://api.example.com/api/posts/11" },        { "@id": "http://api.example.com/api/posts/12" },        { "@id": "http://api.example.com/api/posts/13" },        { "@id": "http://api.example.com/api/posts/14" },        { "@id": "http://api.example.com/api/posts/15" },        { "@id": "http://api.example.com/api/posts/16" },        { "@id": "http://api.example.com/api/posts/17" },        { "@id": "http://api.example.com/api/posts/18" },        { "@id": "http://api.example.com/api/posts/19" }    ],    "search": {        "template": "/api/posts{?search,limit,offset}",        "resolveRelativeUsing": "hydra:Rfc3986",        "mapping": [            {                "variable": "search",                "property": "hydra:freetextQuery",                "required": true,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "limit",                "property": "hydra:limit",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "offset",                "property": "hydra:offset",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            }        ]    }}
+
+

7.11. hydra:headerName

+ + + + + + + + +
Name: + headerName +
Summary: + Name of the header. +
Min cardinality: + 1 +
Max cardinality: + 1 +
Domain: + HeaderSpecification +
Range: + xsd:string +
+
+ +
EXAMPLE: hydra:headerName
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api?documentation",    "@type": "ApiDocumentation",    "entrypoint": "http://api.example.com/api",    "extension": "https://w3id.org/hydra/extension#shacl",    "supportedClass": [        {            "@id": "http://api.example.com/vocab#User",            "title": "User",            "description": "Describes a system user.",            "supportedOperation": [                {                    "method": "PUT",                    "title": "Create new user",                    "description": "Creates a brand new user.",                    "expects": "http://api.example.com/vocab#User",                    "returns": "http://api.example.com/vocab#User",                    "returnsHeader": [                        {                            "headerName": "Content-Type",                            "possibleValue": ["text/turtle", "application/ld+json"],                            "closedSet": true                        }                        "Content-Length"                    ],                    "expectsHeader": [                        "Authorization",                        {                            "headerName": "Content-Type",                            "possibleValue": ["image/gif", "image/png"],                            "closedSet": true                        }                    ]                }            ],            "supportedProperty": [                {                    "property": "http://api.example.com/vocab#login",                    "writable": true,                    "readable": true,                    "required": true                }            ]        }    ]}
+
+

7.12. hydra:last

+ + + + + + + +
Name: + last +
Summary: + The last resource of an interlinked set of resources. +
Max cardinality: + 1 +
Domain: + Resource +
Range: + Resource +
+
+ +
EXAMPLE: hydra:last
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api/posts",    "@type": "Collection",    "view": {        "@id": "http://api.example.com/api/posts?skip=10",        "@type": "PartialCollectionView",        "first": "http://api.example.com/api/posts",        "last": "http://api.example.com/api/posts?skip=100",        "previous": "http://api.example.com/api/posts",        "next": "http://api.example.com/api/posts?skip=20",        "totalItems": 10,    },    "totalItems": 100,    "member": [        { "@id": "http://api.example.com/api/posts/10" },        { "@id": "http://api.example.com/api/posts/11" },        { "@id": "http://api.example.com/api/posts/12" },        { "@id": "http://api.example.com/api/posts/13" },        { "@id": "http://api.example.com/api/posts/14" },        { "@id": "http://api.example.com/api/posts/15" },        { "@id": "http://api.example.com/api/posts/16" },        { "@id": "http://api.example.com/api/posts/17" },        { "@id": "http://api.example.com/api/posts/18" },        { "@id": "http://api.example.com/api/posts/19" }    ],    "search": {        "template": "/api/posts{?search,limit,offset}",        "resolveRelativeUsing": "hydra:Rfc3986",        "mapping": [            {                "variable": "search",                "property": "hydra:freetextQuery",                "required": true,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "limit",                "property": "hydra:limit",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "offset",                "property": "hydra:offset",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            }        ]    }}
+
+

7.13. hydra:limit

+ + + + + + +
Name: + limit +
Summary: + Instructs to limit set only to N elements. +
Max cardinality: + 1 +
Range: + xsd:nonNegativeInteger +
+
+ +
EXAMPLE: hydra:limit
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api/posts",    "@type": "Collection",    "view": {        "@id": "http://api.example.com/api/posts?skip=10",        "@type": "PartialCollectionView",        "first": "http://api.example.com/api/posts",        "last": "http://api.example.com/api/posts?skip=100",        "previous": "http://api.example.com/api/posts",        "next": "http://api.example.com/api/posts?skip=20",        "totalItems": 10,    },    "totalItems": 100,    "member": [        { "@id": "http://api.example.com/api/posts/10" },        { "@id": "http://api.example.com/api/posts/11" },        { "@id": "http://api.example.com/api/posts/12" },        { "@id": "http://api.example.com/api/posts/13" },        { "@id": "http://api.example.com/api/posts/14" },        { "@id": "http://api.example.com/api/posts/15" },        { "@id": "http://api.example.com/api/posts/16" },        { "@id": "http://api.example.com/api/posts/17" },        { "@id": "http://api.example.com/api/posts/18" },        { "@id": "http://api.example.com/api/posts/19" }    ],    "search": {        "template": "/api/posts{?search,limit,offset}",        "resolveRelativeUsing": "hydra:Rfc3986",        "mapping": [            {                "variable": "search",                "property": "hydra:freetextQuery",                "required": true,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "limit",                "property": "hydra:limit",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "offset",                "property": "hydra:offset",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            }        ]    }}
+
+

7.14. hydra:mapping

+ + + + + + + +
Name: + mapping +
Summary: + A variable-to-property mapping of the IRI template. +
Min cardinality: + 1 +
Domain: + IriTemplate +
Range: + IriTemplateMapping +
+
+ +
EXAMPLE: hydra:mapping
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api/posts",    "@type": "Collection",    "view": {        "@id": "http://api.example.com/api/posts?skip=10",        "@type": "PartialCollectionView",        "first": "http://api.example.com/api/posts",        "last": "http://api.example.com/api/posts?skip=100",        "previous": "http://api.example.com/api/posts",        "next": "http://api.example.com/api/posts?skip=20",        "totalItems": 10,    },    "totalItems": 100,    "member": [        { "@id": "http://api.example.com/api/posts/10" },        { "@id": "http://api.example.com/api/posts/11" },        { "@id": "http://api.example.com/api/posts/12" },        { "@id": "http://api.example.com/api/posts/13" },        { "@id": "http://api.example.com/api/posts/14" },        { "@id": "http://api.example.com/api/posts/15" },        { "@id": "http://api.example.com/api/posts/16" },        { "@id": "http://api.example.com/api/posts/17" },        { "@id": "http://api.example.com/api/posts/18" },        { "@id": "http://api.example.com/api/posts/19" }    ],    "search": {        "template": "/api/posts{?search,limit,offset}",        "resolveRelativeUsing": "hydra:Rfc3986",        "mapping": [            {                "variable": "search",                "property": "hydra:freetextQuery",                "required": true,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "limit",                "property": "hydra:limit",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "offset",                "property": "hydra:offset",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            }        ]    }}
+
+

7.15. hydra:member

+ + + + + +
Name: + member +
Summary: + A member of the collection. +
Domain: + Collection +
+
+ +
EXAMPLE: hydra:member
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api/posts",    "@type": "Collection",    "view": {        "@id": "http://api.example.com/api/posts?skip=10",        "@type": "PartialCollectionView",        "first": "http://api.example.com/api/posts",        "last": "http://api.example.com/api/posts?skip=100",        "previous": "http://api.example.com/api/posts",        "next": "http://api.example.com/api/posts?skip=20",        "totalItems": 10,    },    "totalItems": 100,    "member": [        { "@id": "http://api.example.com/api/posts/10" },        { "@id": "http://api.example.com/api/posts/11" },        { "@id": "http://api.example.com/api/posts/12" },        { "@id": "http://api.example.com/api/posts/13" },        { "@id": "http://api.example.com/api/posts/14" },        { "@id": "http://api.example.com/api/posts/15" },        { "@id": "http://api.example.com/api/posts/16" },        { "@id": "http://api.example.com/api/posts/17" },        { "@id": "http://api.example.com/api/posts/18" },        { "@id": "http://api.example.com/api/posts/19" }    ],    "search": {        "template": "/api/posts{?search,limit,offset}",        "resolveRelativeUsing": "hydra:Rfc3986",        "mapping": [            {                "variable": "search",                "property": "hydra:freetextQuery",                "required": true,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "limit",                "property": "hydra:limit",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "offset",                "property": "hydra:offset",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            }        ]    }}
+
+

7.16. hydra:memberAssertion

+ + + + + + +
Name: + memberAssertion +
Summary: + Semantics of each member provided by the collection. +
Domain includes: + Collection, Class +
Range: + +
+
+ +
EXAMPLE: hydra:memberAssertion in context of strongly typed collections
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api",    "collection": [        {            "@id": "http://api.example.com/api/posts",            "@type": "Collection",            "memberAssertion": [                {                    "property": "rdf:type",                    "object": "http://api.example.com/vocab#Post"                }            ]        }    ]}
+
+
+ +
EXAMPLE: hydra:memberAssertion in context of building relation to another resource
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api/posts/1/comments",    "@type": "Collection",    "memberAssertion": [        {            "subject": "http://api.example.com/api/posts/1",            "property": "http://api.example.com/vocab#comment"        }    ]}
+
+
+ +
EXAMPLE: hydra:memberAssertion in context of hydra:ApiDocumentation
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@graph": [        {            "@id": "http://api.example.com/api?documentation",            "@type": "ApiDocumentation",            "entrypoint": "http://api.example.com/api"        },        {            "@id": "http://api.example.com/vocab#comments",            "@type": "hydra:Link",            "supportedOperation": [                {                    "method": "GET",                    "returns": {                        "subClassOf": "hydra:Collection",                        "memberAssertion": {                            "property": "rdf:type",                            "object": "http://api.example.com/vocab#Comment"                        }                    }                }            ]        }    }}
+
+

7.17. hydra:method

+ + + + + + +
Name: + method +
Summary: + The protocol method. +
Domain: + Operation +
Range: + xsd:string +
+
+ +
EXAMPLE: hydra:method
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api?documentation",    "@type": "ApiDocumentation",    "entrypoint": "http://api.example.com/api",    "extension": "https://w3id.org/hydra/extension#shacl",    "supportedClass": [        {            "@id": "http://api.example.com/vocab#User",            "title": "User",            "description": "Describes a system user.",            "supportedOperation": [                {                    "method": "PUT",                    "title": "Create new user",                    "description": "Creates a brand new user.",                    "expects": "http://api.example.com/vocab#User",                    "returns": "http://api.example.com/vocab#User",                    "returnsHeader": [                        {                            "headerName": "Content-Type",                            "possibleValue": ["text/turtle", "application/ld+json"],                            "closedSet": true                        }                        "Content-Length"                    ],                    "expectsHeader": [                        "Authorization",                        {                            "headerName": "Content-Type",                            "possibleValue": ["image/gif", "image/png"],                            "closedSet": true                        }                    ]                }            ],            "supportedProperty": [                {                    "property": "http://api.example.com/vocab#login",                    "writable": true,                    "readable": true,                    "required": true                }            ]        }    ]}
+
+

7.18. hydra:next

+ + + + + + + +
Name: + next +
Summary: + The resource following the current instance + in an interlinked set of resources. +
Max cardinality: + 1 +
Domain: + Resource +
Range: + Resource +
+
+ +
EXAMPLE: hydra:next
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api/posts",    "@type": "Collection",    "view": {        "@id": "http://api.example.com/api/posts?skip=10",        "@type": "PartialCollectionView",        "first": "http://api.example.com/api/posts",        "last": "http://api.example.com/api/posts?skip=100",        "previous": "http://api.example.com/api/posts",        "next": "http://api.example.com/api/posts?skip=20",        "totalItems": 10,    },    "totalItems": 100,    "member": [        { "@id": "http://api.example.com/api/posts/10" },        { "@id": "http://api.example.com/api/posts/11" },        { "@id": "http://api.example.com/api/posts/12" },        { "@id": "http://api.example.com/api/posts/13" },        { "@id": "http://api.example.com/api/posts/14" },        { "@id": "http://api.example.com/api/posts/15" },        { "@id": "http://api.example.com/api/posts/16" },        { "@id": "http://api.example.com/api/posts/17" },        { "@id": "http://api.example.com/api/posts/18" },        { "@id": "http://api.example.com/api/posts/19" }    ],    "search": {        "template": "/api/posts{?search,limit,offset}",        "resolveRelativeUsing": "hydra:Rfc3986",        "mapping": [            {                "variable": "search",                "property": "hydra:freetextQuery",                "required": true,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "limit",                "property": "hydra:limit",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "offset",                "property": "hydra:offset",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            }        ]    }}
+
+

7.19. hydra:object

+ + + + + +
Name: + object +
Summary: + The object. +
Min cardinality: + 1 +
+
+ +
EXAMPLE: hydra:object
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api",    "collection": [        {            "@id": "http://api.example.com/api/posts",            "@type": "Collection",            "memberAssertion": [                {                    "property": "rdf:type",                    "object": "http://api.example.com/vocab#Post"                }            ]        }    ]}
+
+

7.20. hydra:offset

+ + + + + + +
Name: + offset +
Summary: + Instructs to skip N elements of the set. +
Max cardinality: + 1 +
Range: + xsd:nonNegativeInteger +
+
+ +
EXAMPLE: hydra:offset
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api/posts",    "@type": "Collection",    "view": {        "@id": "http://api.example.com/api/posts?skip=10",        "@type": "PartialCollectionView",        "first": "http://api.example.com/api/posts",        "last": "http://api.example.com/api/posts?skip=100",        "previous": "http://api.example.com/api/posts",        "next": "http://api.example.com/api/posts?skip=20",        "totalItems": 10,    },    "totalItems": 100,    "member": [        { "@id": "http://api.example.com/api/posts/10" },        { "@id": "http://api.example.com/api/posts/11" },        { "@id": "http://api.example.com/api/posts/12" },        { "@id": "http://api.example.com/api/posts/13" },        { "@id": "http://api.example.com/api/posts/14" },        { "@id": "http://api.example.com/api/posts/15" },        { "@id": "http://api.example.com/api/posts/16" },        { "@id": "http://api.example.com/api/posts/17" },        { "@id": "http://api.example.com/api/posts/18" },        { "@id": "http://api.example.com/api/posts/19" }    ],    "search": {        "template": "/api/posts{?search,limit,offset}",        "resolveRelativeUsing": "hydra:Rfc3986",        "mapping": [            {                "variable": "search",                "property": "hydra:freetextQuery",                "required": true,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "limit",                "property": "hydra:limit",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "offset",                "property": "hydra:offset",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            }        ]    }}
+
+

7.21. hydra:operation

+ + + + + + +
Name: + operation‎ +
Summary: + An operation supported by the Hydra resource. +
Domain: + Resource +
Range: + Operation +
+
+ +
EXAMPLE: hydra:operation
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api/posts/1",    "operation": [        {            "method": "DELETE",            "title": "Remove",            "description": "Removes post no. 1"        }    ]}
+
+

7.22. hydra:pageIndex

+ + + + + + +
Name: + pageIndex +
Summary: + Instructs to provide a specific page of the collection + at a given index. +
Max cardinality: + 1 +
Range: + xsd:nonNegativeInteger +
+
+ +
EXAMPLE: hydra:pageIndex
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api/posts",    "@type": "Collection",    "view": {        "@id": "http://api.example.com/api/posts?skip=10",        "@type": "PartialCollectionView",        "first": "http://api.example.com/api/posts",        "last": "http://api.example.com/api/posts?skip=100",        "previous": "http://api.example.com/api/posts",        "next": "http://api.example.com/api/posts?skip=20",        "totalItems": 10,    },    "totalItems": 100,    "member": [        { "@id": "http://api.example.com/api/posts/10" },        { "@id": "http://api.example.com/api/posts/11" },        { "@id": "http://api.example.com/api/posts/12" },        { "@id": "http://api.example.com/api/posts/13" },        { "@id": "http://api.example.com/api/posts/14" },        { "@id": "http://api.example.com/api/posts/15" },        { "@id": "http://api.example.com/api/posts/16" },        { "@id": "http://api.example.com/api/posts/17" },        { "@id": "http://api.example.com/api/posts/18" },        { "@id": "http://api.example.com/api/posts/19" }    ],    "search": {        "template": "/api/posts{?search,page,limit}",        "resolveRelativeUsing": "hydra:Rfc3986",        "mapping": [            {                "variable": "search",                "property": "hydra:freetextQuery",                "required": true,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "limit",                "property": "hydra:limit",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "page",                "property": "hydra:pageIndex",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            }        ]    }}
+
+

7.23. hydra:pageReference

+ + + + + +
Name: + pageReference +
Summary: + Instructs to provide a specific page reference + of the collection. +
Max cardinality: + 1 +
+
+ +
EXAMPLE: hydra:pageReference
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api/posts",    "@type": "Collection",    "view": {        "@id": "http://api.example.com/api/posts?skip=10",        "@type": "PartialCollectionView",        "first": "http://api.example.com/api/posts",        "last": "http://api.example.com/api/posts?skip=100",        "previous": "http://api.example.com/api/posts",        "next": "http://api.example.com/api/posts?skip=20",        "totalItems": 10,    },    "totalItems": 100,    "member": [        { "@id": "http://api.example.com/api/posts/10" },        { "@id": "http://api.example.com/api/posts/11" },        { "@id": "http://api.example.com/api/posts/12" },        { "@id": "http://api.example.com/api/posts/13" },        { "@id": "http://api.example.com/api/posts/14" },        { "@id": "http://api.example.com/api/posts/15" },        { "@id": "http://api.example.com/api/posts/16" },        { "@id": "http://api.example.com/api/posts/17" },        { "@id": "http://api.example.com/api/posts/18" },        { "@id": "http://api.example.com/api/posts/19" }    ],    "search": {        "template": "/api/posts{?search,partOfDay,limit}",        "resolveRelativeUsing": "hydra:Rfc3986",        "mapping": [            {                "variable": "search",                "property": "hydra:freetextQuery",                "required": true,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "limit",                "property": "hydra:limit",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "partOfDay",                "property": "hydra:pageReference",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            }        ]    }}
+
+

7.24. hydra:possibleStatus

+ + + + + + +
Name: + possibleStatus +
Summary: + A status that might be returned by the Web API (other + statuses should be expected and properly handled as well). +
Domain includes: + ApiDocumentation, Operation +
Range: + Status +
+
+ +
EXAMPLE: hydra:possibleStatus
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api/posts/1",    "operation": [        {            "method": "DELETE",            "title": "Remove",            "description": "Removes post no. 1",            "possibleStatus": [                {                    "@type": "Status",                    "statusCode": 303                }            ]        }    ]}
+
+

7.25. hydra:possibleValue

+ + + + + + + +
Name: + possibleValue +
Summary: + Possible value of the header. +
Min cardinality: + 1 +
Domain: + HeaderSpecification +
Range: + xsd:string +
+
+ +
EXAMPLE: hydra:possibleValue
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api?documentation",    "@type": "ApiDocumentation",    "entrypoint": "http://api.example.com/api",    "extension": "https://w3id.org/hydra/extension#shacl",    "supportedClass": [        {            "@id": "http://api.example.com/vocab#User",            "title": "User",            "description": "Describes a system user.",            "supportedOperation": [                {                    "method": "PUT",                    "title": "Create new user",                    "description": "Creates a brand new user.",                    "expects": "http://api.example.com/vocab#User",                    "returns": "http://api.example.com/vocab#User",                    "returnsHeader": [                        {                            "headerName": "Content-Type",                            "possibleValue": ["text/turtle", "application/ld+json"],                            "closedSet": true                        }                        "Content-Length"                    ],                    "expectsHeader": [                        "Authorization",                        {                            "headerName": "Content-Type",                            "possibleValue": ["image/gif", "image/png"],                            "closedSet": true                        }                    ]                }            ],            "supportedProperty": [                {                    "property": "http://api.example.com/vocab#login",                    "writable": true,                    "readable": true,                    "required": true                }            ]        }    ]}
+
+

7.26. hydra:previous

+ + + + + + + +
Name: + previous +
Summary: + The resource preceding the current instance + in an interlinked set of resources. +
Max cardinality: + 1 +
Domain: + Resource +
Range: + Resource +
+
+ +
EXAMPLE: hydra:previous
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api/posts",    "@type": "Collection",    "view": {        "@id": "http://api.example.com/api/posts?skip=10",        "@type": "PartialCollectionView",        "first": "http://api.example.com/api/posts",        "last": "http://api.example.com/api/posts?skip=100",        "previous": "http://api.example.com/api/posts",        "next": "http://api.example.com/api/posts?skip=20",        "totalItems": 10,    },    "totalItems": 100,    "member": [        { "@id": "http://api.example.com/api/posts/10" },        { "@id": "http://api.example.com/api/posts/11" },        { "@id": "http://api.example.com/api/posts/12" },        { "@id": "http://api.example.com/api/posts/13" },        { "@id": "http://api.example.com/api/posts/14" },        { "@id": "http://api.example.com/api/posts/15" },        { "@id": "http://api.example.com/api/posts/16" },        { "@id": "http://api.example.com/api/posts/17" },        { "@id": "http://api.example.com/api/posts/18" },        { "@id": "http://api.example.com/api/posts/19" }    ],    "search": {        "template": "/api/posts{?search,limit,offset}",        "resolveRelativeUsing": "hydra:Rfc3986",        "mapping": [            {                "variable": "search",                "property": "hydra:freetextQuery",                "required": true,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "limit",                "property": "hydra:limit",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "offset",                "property": "hydra:offset",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            }        ]    }}
+
+

7.27. hydra:property

+ (only when used in context of memberAssertion) + + + + + + + +
Name: + property +
Summary: + A property. +
Min cardinality: + 1 +
Domain includes: + SupportedProperty, IriTemplateMapping +
Range: + rdf:Property +
+
+ +
EXAMPLE: hydra:property in context of hydra:SupportedProperty
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api?documentation",    "@type": "ApiDocumentation",    "entrypoint": "http://api.example.com/api",    "extension": "https://w3id.org/hydra/extension#shacl",    "supportedClass": [        {            "@id": "http://api.example.com/vocab#User",            "title": "User",            "description": "Describes a system user.",            "supportedOperation": [                {                    "method": "PUT",                    "title": "Create new user",                    "description": "Creates a brand new user.",                    "expects": "http://api.example.com/vocab#User",                    "returns": "http://api.example.com/vocab#User",                    "returnsHeader": [                        {                            "headerName": "Content-Type",                            "possibleValue": ["text/turtle", "application/ld+json"],                            "closedSet": true                        }                        "Content-Length"                    ],                    "expectsHeader": [                        "Authorization",                        {                            "headerName": "Content-Type",                            "possibleValue": ["image/gif", "image/png"],                            "closedSet": true                        }                    ]                }            ],            "supportedProperty": [                {                    "property": "http://api.example.com/vocab#login",                    "writable": true,                    "readable": true,                    "required": true                }            ]        }    ]}
+
+
+ +
EXAMPLE: hydra:property in context of hydra:IriTemplateMapping
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api/posts",    "@type": "Collection",    "view": {        "@id": "http://api.example.com/api/posts?skip=10",        "@type": "PartialCollectionView",        "first": "http://api.example.com/api/posts",        "last": "http://api.example.com/api/posts?skip=100",        "previous": "http://api.example.com/api/posts",        "next": "http://api.example.com/api/posts?skip=20",        "totalItems": 10,    },    "totalItems": 100,    "member": [        { "@id": "http://api.example.com/api/posts/10" },        { "@id": "http://api.example.com/api/posts/11" },        { "@id": "http://api.example.com/api/posts/12" },        { "@id": "http://api.example.com/api/posts/13" },        { "@id": "http://api.example.com/api/posts/14" },        { "@id": "http://api.example.com/api/posts/15" },        { "@id": "http://api.example.com/api/posts/16" },        { "@id": "http://api.example.com/api/posts/17" },        { "@id": "http://api.example.com/api/posts/18" },        { "@id": "http://api.example.com/api/posts/19" }    ],    "search": {        "template": "/api/posts{?search,limit,offset}",        "resolveRelativeUsing": "hydra:Rfc3986",        "mapping": [            {                "variable": "search",                "property": "hydra:freetextQuery",                "required": true,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "limit",                "property": "hydra:limit",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "offset",                "property": "hydra:offset",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            }        ]    }}
+
+
+ +
EXAMPLE: hydra:property in context of strongly typed collections
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api",    "collection": [        {            "@id": "http://api.example.com/api/posts",            "@type": "Collection",            "memberAssertion": [                {                    "property": "rdf:type",                    "object": "http://api.example.com/vocab#Post"                }            ]        }    ]}
+
+

7.28. hydra:readable

+ + + + + + + +
Name: + readable +
Summary: + True if the client can retrieve the property’s value, + false otherwise. +
Max cardinality: + 1 +
Domain: + SupportedProperty +
Range: + xsd:boolean +
+
+ +
EXAMPLE: hydra:readable
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api?documentation",    "@type": "ApiDocumentation",    "entrypoint": "http://api.example.com/api",    "extension": "https://w3id.org/hydra/extension#shacl",    "supportedClass": [        {            "@id": "http://api.example.com/vocab#User",            "title": "User",            "description": "Describes a system user.",            "supportedOperation": [                {                    "method": "PUT",                    "title": "Create new user",                    "description": "Creates a brand new user.",                    "expects": "http://api.example.com/vocab#User",                    "returns": "http://api.example.com/vocab#User",                    "returnsHeader": [                        {                            "headerName": "Content-Type",                            "possibleValue": ["text/turtle", "application/ld+json"],                            "closedSet": true                        }                        "Content-Length"                    ],                    "expectsHeader": [                        "Authorization",                        {                            "headerName": "Content-Type",                            "possibleValue": ["image/gif", "image/png"],                            "closedSet": true                        }                    ]                }            ],            "supportedProperty": [                {                    "property": "http://api.example.com/vocab#login",                    "writable": true,                    "readable": true,                    "required": true                }            ]        }    ]}
+
+

7.29. hydra:required

+ + + + + + + +
Name: + required +
Summary: + True if the property is required, false otherwise. +
Max cardinality: + 1 +
Domain includes: + SupportedProperty, IriTemplateMapping +
Range: + xsd:boolean +
+
+ +
EXAMPLE: hydra:required in context of hydra:SupportedProperty
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api?documentation",    "@type": "ApiDocumentation",    "entrypoint": "http://api.example.com/api",    "extension": "https://w3id.org/hydra/extension#shacl",    "supportedClass": [        {            "@id": "http://api.example.com/vocab#User",            "title": "User",            "description": "Describes a system user.",            "supportedOperation": [                {                    "method": "PUT",                    "title": "Create new user",                    "description": "Creates a brand new user.",                    "expects": "http://api.example.com/vocab#User",                    "returns": "http://api.example.com/vocab#User",                    "returnsHeader": [                        {                            "headerName": "Content-Type",                            "possibleValue": ["text/turtle", "application/ld+json"],                            "closedSet": true                        }                        "Content-Length"                    ],                    "expectsHeader": [                        "Authorization",                        {                            "headerName": "Content-Type",                            "possibleValue": ["image/gif", "image/png"],                            "closedSet": true                        }                    ]                }            ],            "supportedProperty": [                {                    "property": "http://api.example.com/vocab#login",                    "writable": true,                    "readable": true,                    "required": true                }            ]        }    ]}
+
+
+ +
EXAMPLE: hydra:required in context of hydra:IriTemplateMapping
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api/posts",    "@type": "Collection",    "view": {        "@id": "http://api.example.com/api/posts?skip=10",        "@type": "PartialCollectionView",        "first": "http://api.example.com/api/posts",        "last": "http://api.example.com/api/posts?skip=100",        "previous": "http://api.example.com/api/posts",        "next": "http://api.example.com/api/posts?skip=20",        "totalItems": 10,    },    "totalItems": 100,    "member": [        { "@id": "http://api.example.com/api/posts/10" },        { "@id": "http://api.example.com/api/posts/11" },        { "@id": "http://api.example.com/api/posts/12" },        { "@id": "http://api.example.com/api/posts/13" },        { "@id": "http://api.example.com/api/posts/14" },        { "@id": "http://api.example.com/api/posts/15" },        { "@id": "http://api.example.com/api/posts/16" },        { "@id": "http://api.example.com/api/posts/17" },        { "@id": "http://api.example.com/api/posts/18" },        { "@id": "http://api.example.com/api/posts/19" }    ],    "search": {        "template": "/api/posts{?search,limit,offset}",        "resolveRelativeUsing": "hydra:Rfc3986",        "mapping": [            {                "variable": "search",                "property": "hydra:freetextQuery",                "required": true,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "limit",                "property": "hydra:limit",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "offset",                "property": "hydra:offset",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            }        ]    }}
+
+

7.30. hydra:resolveRelativeUsing

+ + + + + +
Name: + resolveRelativeUsing +
Summary: + Instructs on how to resolve relative Uri created + by the Iri template resolution. +
Max cardinality: + 1 +
+
+ +
EXAMPLE: hydra:resolveRelativeUsing
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api/posts",    "@type": "Collection",    "view": {        "@id": "http://api.example.com/api/posts?skip=10",        "@type": "PartialCollectionView",        "first": "http://api.example.com/api/posts",        "last": "http://api.example.com/api/posts?skip=100",        "previous": "http://api.example.com/api/posts",        "next": "http://api.example.com/api/posts?skip=20",        "totalItems": 10,    },    "totalItems": 100,    "member": [        { "@id": "http://api.example.com/api/posts/10" },        { "@id": "http://api.example.com/api/posts/11" },        { "@id": "http://api.example.com/api/posts/12" },        { "@id": "http://api.example.com/api/posts/13" },        { "@id": "http://api.example.com/api/posts/14" },        { "@id": "http://api.example.com/api/posts/15" },        { "@id": "http://api.example.com/api/posts/16" },        { "@id": "http://api.example.com/api/posts/17" },        { "@id": "http://api.example.com/api/posts/18" },        { "@id": "http://api.example.com/api/posts/19" }    ],    "search": {        "template": "/api/posts{?search,limit,offset}",        "resolveRelativeUsing": "hydra:Rfc3986",        "mapping": [            {                "variable": "search",                "property": "hydra:freetextQuery",                "required": true,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "limit",                "property": "hydra:limit",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "offset",                "property": "hydra:offset",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            }        ]    }}
+
+

7.31. hydra:returns

+ + + + + + +
Name: + returns +
Summary: + The information returned by the Web API on success. +
Domain: + Operation +
Range includes: + rdfs:Resource, Resource, rdfs:Class, Class +
+
+ +
EXAMPLE: hydra:returns
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api?documentation",    "@type": "ApiDocumentation",    "entrypoint": "http://api.example.com/api",    "extension": "https://w3id.org/hydra/extension#shacl",    "supportedClass": [        {            "@id": "http://api.example.com/vocab#User",            "title": "User",            "description": "Describes a system user.",            "supportedOperation": [                {                    "method": "PUT",                    "title": "Create new user",                    "description": "Creates a brand new user.",                    "expects": "http://api.example.com/vocab#User",                    "returns": "http://api.example.com/vocab#User",                    "returnsHeader": [                        {                            "headerName": "Content-Type",                            "possibleValue": ["text/turtle", "application/ld+json"],                            "closedSet": true                        }                        "Content-Length"                    ],                    "expectsHeader": [                        "Authorization",                        {                            "headerName": "Content-Type",                            "possibleValue": ["image/gif", "image/png"],                            "closedSet": true                        }                    ]                }            ],            "supportedProperty": [                {                    "property": "http://api.example.com/vocab#login",                    "writable": true,                    "readable": true,                    "required": true                }            ]        }    ]}
+
+

7.32. hydra:returnsHeader

+ + + + + + +
Name: + returnsHeader +
Summary: + Name of the header returned by the operation. +
Domain: + Operation +
Range includes: + xsd:string, HeaderSpecification +
+
+ +
EXAMPLE: hydra:returnsHeader
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api?documentation",    "@type": "ApiDocumentation",    "entrypoint": "http://api.example.com/api",    "extension": "https://w3id.org/hydra/extension#shacl",    "supportedClass": [        {            "@id": "http://api.example.com/vocab#User",            "title": "User",            "description": "Describes a system user.",            "supportedOperation": [                {                    "method": "PUT",                    "title": "Create new user",                    "description": "Creates a brand new user.",                    "expects": "http://api.example.com/vocab#User",                    "returns": "http://api.example.com/vocab#User",                    "returnsHeader": [                        {                            "headerName": "Content-Type",                            "possibleValue": ["text/turtle", "application/ld+json"],                            "closedSet": true                        }                        "Content-Length"                    ],                    "expectsHeader": [                        "Authorization",                        {                            "headerName": "Content-Type",                            "possibleValue": ["image/gif", "image/png"],                            "closedSet": true                        }                    ]                }            ],            "supportedProperty": [                {                    "property": "http://api.example.com/vocab#login",                    "writable": true,                    "readable": true,                    "required": true                }            ]        }    ]}
+
+ + + + + + + +
Name: + search +
Summary: + A Iri template that can be used to query a collection. +
Domain: + Resource +
Range: + IriTemplate +
+
+ +
EXAMPLE: hydra:search
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api/posts",    "@type": "Collection",    "view": {        "@id": "http://api.example.com/api/posts?skip=10",        "@type": "PartialCollectionView",        "first": "http://api.example.com/api/posts",        "last": "http://api.example.com/api/posts?skip=100",        "previous": "http://api.example.com/api/posts",        "next": "http://api.example.com/api/posts?skip=20",        "totalItems": 10,    },    "totalItems": 100,    "member": [        { "@id": "http://api.example.com/api/posts/10" },        { "@id": "http://api.example.com/api/posts/11" },        { "@id": "http://api.example.com/api/posts/12" },        { "@id": "http://api.example.com/api/posts/13" },        { "@id": "http://api.example.com/api/posts/14" },        { "@id": "http://api.example.com/api/posts/15" },        { "@id": "http://api.example.com/api/posts/16" },        { "@id": "http://api.example.com/api/posts/17" },        { "@id": "http://api.example.com/api/posts/18" },        { "@id": "http://api.example.com/api/posts/19" }    ],    "search": {        "template": "/api/posts{?search,limit,offset}",        "resolveRelativeUsing": "hydra:Rfc3986",        "mapping": [            {                "variable": "search",                "property": "hydra:freetextQuery",                "required": true,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "limit",                "property": "hydra:limit",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "offset",                "property": "hydra:offset",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            }        ]    }}
+
+

7.34. hydra:statusCode

+ + + + + + +
Name: + statusCode +
Summary: + The response status code. Please note it may happen this + value will be different to actual status code received. +
Domain: + Status +
Range: + xsd:integer +
+
+ +
EXAMPLE: hydra:statusCode in context of hydra:Error
+
HTTP/1.1 400 Bad requestContent-Type: application/problem+jsonLink: <http://www.w3.org/ns/hydra/error>; rel="http://www.w3.org/ns/json-ld#context"{    "type": "https://api.example.com/vocab#NullReferenceException",    "@type": "http://www.w3.org/ns/hydra/core#Error",    "title": "The request cannot be processed.",    "detail": "Provided value cannot be 'null'.",    "instance": "http://api.example.com/api/posts",    "status": 404}
+
+
+ +
EXAMPLE: hydra:statusCode in context of hydra:Status
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api/posts/1",    "operation": [        {            "method": "DELETE",            "title": "Remove",            "description": "Removes post no. 1",            "possibleStatus": [                {                    "@type": "Status",                    "statusCode": 303                }            ]        }    ]}
+
+

7.35. hydra:subject

+ + + + + +
Name: + subject +
Summary: + The subject. +
Min cardinality: + 1 +
+
+ +
EXAMPLE: hydra:subject
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api/posts/1/comments",    "@type": "Collection",    "memberAssertion": [        {            "subject": "http://api.example.com/api/posts/1",            "property": "http://api.example.com/vocab#comment"        }    ]}
+
+

7.36. hydra:supportedClass

+ + + + + + +
Name: + supportedClass +
Summary: + A class known to be supported by the Web API. +
Domain: + ApiDocumentation +
Range: + rdfs:Class +
+
+ +
EXAMPLE: hydra:supportedClass
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api?documentation",    "@type": "ApiDocumentation",    "entrypoint": "http://api.example.com/api",    "extension": "https://w3id.org/hydra/extension#shacl",    "supportedClass": [        {            "@id": "http://api.example.com/vocab#User",            "title": "User",            "description": "Describes a system user.",            "supportedOperation": [                {                    "method": "PUT",                    "title": "Create new user",                    "description": "Creates a brand new user.",                    "expects": "http://api.example.com/vocab#User",                    "returns": "http://api.example.com/vocab#User",                    "returnsHeader": [                        {                            "headerName": "Content-Type",                            "possibleValue": ["text/turtle", "application/ld+json"],                            "closedSet": true                        }                        "Content-Length"                    ],                    "expectsHeader": [                        "Authorization",                        {                            "headerName": "Content-Type",                            "possibleValue": ["image/gif", "image/png"],                            "closedSet": true                        }                    ]                }            ],            "supportedProperty": [                {                    "property": "http://api.example.com/vocab#login",                    "writable": true,                    "readable": true,                    "required": true                }            ]        }    ]}
+
+

7.37. hydra:supportedOperation

+ + + + + + +
Name: + supportedOperation +
Summary: + An operation supported by instances of the specific Hydra + class, or the target of the Hydra link, or Iri template. +
Domain includes: + rdfs:Class, Class, Link, TemplatedLink, SupportedProperty +
Range: + Operation +
+
+ +
EXAMPLE: hydra:supportedOperation in context of hydra:SupportedClass
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api?documentation",    "@type": "ApiDocumentation",    "entrypoint": "http://api.example.com/api",    "extension": "https://w3id.org/hydra/extension#shacl",    "supportedClass": [        {            "@id": "http://api.example.com/vocab#User",            "title": "User",            "description": "Describes a system user.",            "supportedOperation": [                {                    "method": "PUT",                    "title": "Create new user",                    "description": "Creates a brand new user.",                    "expects": "http://api.example.com/vocab#User",                    "returns": "http://api.example.com/vocab#User",                    "returnsHeader": [                        {                            "headerName": "Content-Type",                            "possibleValue": ["text/turtle", "application/ld+json"],                            "closedSet": true                        }                        "Content-Length"                    ],                    "expectsHeader": [                        "Authorization",                        {                            "headerName": "Content-Type",                            "possibleValue": ["image/gif", "image/png"],                            "closedSet": true                        }                    ]                }            ],            "supportedProperty": [                {                    "property": "http://api.example.com/vocab#login",                    "writable": true,                    "readable": true,                    "required": true                }            ]        }    ]}
+
+
+ +
EXAMPLE: hydra:supportedOperation in context of hydra:TemplatedLink
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api/posts",    "@type": "Collection",    "view": {        "@id": "http://api.example.com/api/posts?skip=10",        "@type": "PartialCollectionView",        "first": "http://api.example.com/api/posts",        "last": "http://api.example.com/api/posts?skip=100",        "previous": "http://api.example.com/api/posts",        "next": "http://api.example.com/api/posts?skip=20",        "totalItems": 10,    },    "totalItems": 100,    "member": [        { "@id": "http://api.example.com/api/posts/10" },        { "@id": "http://api.example.com/api/posts/11" },        { "@id": "http://api.example.com/api/posts/12" },        { "@id": "http://api.example.com/api/posts/13" },        { "@id": "http://api.example.com/api/posts/14" },        { "@id": "http://api.example.com/api/posts/15" },        { "@id": "http://api.example.com/api/posts/16" },        { "@id": "http://api.example.com/api/posts/17" },        { "@id": "http://api.example.com/api/posts/18" },        { "@id": "http://api.example.com/api/posts/19" }    ],    "search": {        "template": "/api/posts{?search}",        "resolveRelativeUsing": "hydra:Rfc3986",        "supportedOperation": {            "method": "POST"        },        "mapping": [            {                "variable": "search",                "property": "hydra:freetextQuery",                "required": true,                "variableRepresentation": "hydra:BasicRepresentation"            }        ]    }}
+
+
+ +
EXAMPLE: hydra:supportedOperation in context of hydra:Link
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@graph": [        {            "@id": "http://api.example.com/api/posts/1",            "http://api.example.com/vocab#comment":                "http://api.example.com/api/posts/1/comments"        },        {            "@id": "http://api.example.com/vocab#comment",            "@type": "hydra:Link",            "supportedOperation": {                "method": "GET",                "returns": "http://api.example.com/vocab#Comment            }        }    ]}
+
+

7.38. hydra:supportedProperty

+ + + + + + +
Name: + supportedProperty‎ +
Summary: + The properties known to be supported by a Hydra class. +
Domain: + rdfs:Class +
Range: + SupportedProperty +
+
+ +
EXAMPLE: hydra:supportedProperty
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api?documentation",    "@type": "ApiDocumentation",    "entrypoint": "http://api.example.com/api",    "extension": "https://w3id.org/hydra/extension#shacl",    "supportedClass": [        {            "@id": "http://api.example.com/vocab#User",            "title": "User",            "description": "Describes a system user.",            "supportedOperation": [                {                    "method": "PUT",                    "title": "Create new user",                    "description": "Creates a brand new user.",                    "expects": "http://api.example.com/vocab#User",                    "returns": "http://api.example.com/vocab#User",                    "returnsHeader": [                        {                            "headerName": "Content-Type",                            "possibleValue": ["text/turtle", "application/ld+json"],                            "closedSet": true                        }                        "Content-Length"                    ],                    "expectsHeader": [                        "Authorization",                        {                            "headerName": "Content-Type",                            "possibleValue": ["image/gif", "image/png"],                            "closedSet": true                        }                    ]                }            ],            "supportedProperty": [                {                    "property": "http://api.example.com/vocab#login",                    "writable": true,                    "readable": true,                    "required": true                }            ]        }    ]}
+
+

7.39. hydra:template

+ + + + + + + + +
Name: + template +
Summary: + A templated string with placeholders. The literal’s + datatype indicates the template syntax; if not specified, + hydra:Rfc6570Template is assumed. +
Min cardinality: + 1 +
Max cardinality: + 1 +
Domain: + IriTemplate +
Range: + Rfc6570Template +
+
+ +
EXAMPLE: hydra:template
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api/posts",    "@type": "Collection",    "view": {        "@id": "http://api.example.com/api/posts?skip=10",        "@type": "PartialCollectionView",        "first": "http://api.example.com/api/posts",        "last": "http://api.example.com/api/posts?skip=100",        "previous": "http://api.example.com/api/posts",        "next": "http://api.example.com/api/posts?skip=20",        "totalItems": 10,    },    "totalItems": 100,    "member": [        { "@id": "http://api.example.com/api/posts/10" },        { "@id": "http://api.example.com/api/posts/11" },        { "@id": "http://api.example.com/api/posts/12" },        { "@id": "http://api.example.com/api/posts/13" },        { "@id": "http://api.example.com/api/posts/14" },        { "@id": "http://api.example.com/api/posts/15" },        { "@id": "http://api.example.com/api/posts/16" },        { "@id": "http://api.example.com/api/posts/17" },        { "@id": "http://api.example.com/api/posts/18" },        { "@id": "http://api.example.com/api/posts/19" }    ],    "search": {        "template": "/api/posts{?search,limit,offset}",        "resolveRelativeUsing": "hydra:Rfc3986",        "mapping": [            {                "variable": "search",                "property": "hydra:freetextQuery",                "required": true,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "limit",                "property": "hydra:limit",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "offset",                "property": "hydra:offset",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            }        ]    }}
+
+

7.40. hydra:title

+ + + + + + + +
Name: + title +
Summary: + A title, often used along with a description. +
Max cardinality: + 1 +
Domain includes: + ApiDocumentation, Status, Class, SupportedProperty, Operation, Link, TemplatedLink +
Range: + xsd:string +
+
+ +
EXAMPLE: hydra:title
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api?documentation",    "@type": "ApiDocumentation",    "entrypoint": "http://api.example.com/api",    "extension": "https://w3id.org/hydra/extension#shacl",    "supportedClass": [        {            "@id": "http://api.example.com/vocab#User",            "title": "User",            "description": "Describes a system user.",            "supportedOperation": [                {                    "method": "PUT",                    "title": "Create new user",                    "description": "Creates a brand new user.",                    "expects": "http://api.example.com/vocab#User",                    "returns": "http://api.example.com/vocab#User",                    "returnsHeader": [                        {                            "headerName": "Content-Type",                            "possibleValue": ["text/turtle", "application/ld+json"],                            "closedSet": true                        }                        "Content-Length"                    ],                    "expectsHeader": [                        "Authorization",                        {                            "headerName": "Content-Type",                            "possibleValue": ["image/gif", "image/png"],                            "closedSet": true                        }                    ]                }            ],            "supportedProperty": [                {                    "property": "http://api.example.com/vocab#login",                    "writable": true,                    "readable": true,                    "required": true                }            ]        }    ]}
+
+

7.41. hydra:totalItems

+ + + + + + + +
Name: + totalItems +
Summary: + The total number of items referenced by a collection. +
Max cardinality: + 1 +
Domain: + Collection +
Range: + xsd:integer +
+
+ +
EXAMPLE: hydra:totalItems
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api/posts",    "@type": "Collection",    "view": {        "@id": "http://api.example.com/api/posts?skip=10",        "@type": "PartialCollectionView",        "first": "http://api.example.com/api/posts",        "last": "http://api.example.com/api/posts?skip=100",        "previous": "http://api.example.com/api/posts",        "next": "http://api.example.com/api/posts?skip=20",        "totalItems": 10,    },    "totalItems": 100,    "member": [        { "@id": "http://api.example.com/api/posts/10" },        { "@id": "http://api.example.com/api/posts/11" },        { "@id": "http://api.example.com/api/posts/12" },        { "@id": "http://api.example.com/api/posts/13" },        { "@id": "http://api.example.com/api/posts/14" },        { "@id": "http://api.example.com/api/posts/15" },        { "@id": "http://api.example.com/api/posts/16" },        { "@id": "http://api.example.com/api/posts/17" },        { "@id": "http://api.example.com/api/posts/18" },        { "@id": "http://api.example.com/api/posts/19" }    ],    "search": {        "template": "/api/posts{?search,limit,offset}",        "resolveRelativeUsing": "hydra:Rfc3986",        "mapping": [            {                "variable": "search",                "property": "hydra:freetextQuery",                "required": true,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "limit",                "property": "hydra:limit",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "offset",                "property": "hydra:offset",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            }        ]    }}
+
+

7.42. hydra:variable

+ + + + + + + + +
Name: + variable +
Summary: + An Iri template variable. +
Min cardinality: + 1 +
Max cardinality: + 1 +
Domain: + IriTemplateMapping +
Range: + xsd:string +
+
+ +
EXAMPLE: hydra:variable
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api/posts",    "@type": "Collection",    "view": {        "@id": "http://api.example.com/api/posts?skip=10",        "@type": "PartialCollectionView",        "first": "http://api.example.com/api/posts",        "last": "http://api.example.com/api/posts?skip=100",        "previous": "http://api.example.com/api/posts",        "next": "http://api.example.com/api/posts?skip=20",        "totalItems": 10,    },    "totalItems": 100,    "member": [        { "@id": "http://api.example.com/api/posts/10" },        { "@id": "http://api.example.com/api/posts/11" },        { "@id": "http://api.example.com/api/posts/12" },        { "@id": "http://api.example.com/api/posts/13" },        { "@id": "http://api.example.com/api/posts/14" },        { "@id": "http://api.example.com/api/posts/15" },        { "@id": "http://api.example.com/api/posts/16" },        { "@id": "http://api.example.com/api/posts/17" },        { "@id": "http://api.example.com/api/posts/18" },        { "@id": "http://api.example.com/api/posts/19" }    ],    "search": {        "template": "/api/posts{?search,limit,offset}",        "resolveRelativeUsing": "hydra:Rfc3986",        "mapping": [            {                "variable": "search",                "property": "hydra:freetextQuery",                "required": true,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "limit",                "property": "hydra:limit",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "offset",                "property": "hydra:offset",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            }        ]    }}
+
+

7.43. hydra:variableRepresentation

+ + + + + + + +
Name: + variableRepresentation‎ +
Summary: + The representation format to use when expanding + the Iri template. +
Max cardinality: + 1 +
Domain: + IriTemplateMapping +
Range: + VariableRepresentation +
+
+ +
EXAMPLE: hydra:variableRepresentation
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api/posts",    "@type": "Collection",hydra:view    "view": {        "@id": "http://api.example.com/api/posts?skip=10",        "@type": "PartialCollectionView",        "first": "http://api.example.com/api/posts",        "last": "http://api.example.com/api/posts?skip=100",        "previous": "http://api.example.com/api/posts",        "next": "http://api.example.com/api/posts?skip=20",        "totalItems": 10,    },    "totalItems": 100,    "member": [        { "@id": "http://api.example.com/api/posts/10" },        { "@id": "http://api.example.com/api/posts/11" },        { "@id": "http://api.example.com/api/posts/12" },        { "@id": "http://api.example.com/api/posts/13" },        { "@id": "http://api.example.com/api/posts/14" },        { "@id": "http://api.example.com/api/posts/15" },        { "@id": "http://api.example.com/api/posts/16" },        { "@id": "http://api.example.com/api/posts/17" },        { "@id": "http://api.example.com/api/posts/18" },        { "@id": "http://api.example.com/api/posts/19" }    ],    "search": {        "template": "/api/posts{?search,limit,offset}",        "resolveRelativeUsing": "hydra:Rfc3986",        "mapping": [            {                "variable": "search",                "property": "hydra:freetextQuery",                "required": true,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "limit",                "property": "hydra:limit",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "offset",                "property": "hydra:offset",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            }        ]    }}
+
+

7.44. hydra:view

+ + + + + +
Name: + view +
Summary: + A specific view of a resource. +
Max cardinality: + 1 +
+
+ +
EXAMPLE: hydra:view
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api/posts",    "@type": "Collection",    "view": {        "@id": "http://api.example.com/api/posts?skip=10",        "@type": "PartialCollectionView",        "first": "http://api.example.com/api/posts",        "last": "http://api.example.com/api/posts?skip=100",        "previous": "http://api.example.com/api/posts",        "next": "http://api.example.com/api/posts?skip=20",        "totalItems": 10,    },    "totalItems": 100,    "member": [        { "@id": "http://api.example.com/api/posts/10" },        { "@id": "http://api.example.com/api/posts/11" },        { "@id": "http://api.example.com/api/posts/12" },        { "@id": "http://api.example.com/api/posts/13" },        { "@id": "http://api.example.com/api/posts/14" },        { "@id": "http://api.example.com/api/posts/15" },        { "@id": "http://api.example.com/api/posts/16" },        { "@id": "http://api.example.com/api/posts/17" },        { "@id": "http://api.example.com/api/posts/18" },        { "@id": "http://api.example.com/api/posts/19" }    ],    "search": {        "template": "/api/posts{?search,limit,offset}",        "resolveRelativeUsing": "hydra:Rfc3986",        "mapping": [            {                "variable": "search",                "property": "hydra:freetextQuery",                "required": true,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "limit",                "property": "hydra:limit",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            },            {                "variable": "offset",                "property": "hydra:offset",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation"            }        ]    }}
+
+

7.45. hydra:writable

+ + + + + + + +
Name: + writable +
Summary: + True if the client can change the property’s value, + false otherwise. +
Max cardinality: + 1 +
Domain: + SupportedProperty +
Range: + xsd:boolean +
+
+ +
EXAMPLE: hydra:writable
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api?documentation",    "@type": "ApiDocumentation",    "entrypoint": "http://api.example.com/api",    "extension": "https://w3id.org/hydra/extension#shacl",    "supportedClass": [        {            "@id": "http://api.example.com/vocab#User",            "label": "User",            "description": "Describes a system user.",            "supportedOperation": [                {                    "method": "PUT",                    "label": "Create new user",                    "description": "Creates a brand new user.",                    "expects": "http://api.example.com/vocab#User",                    "returns": "http://api.example.com/vocab#User",                    "returnsHeader": [                        {                            "headerName": "Content-Type",                            "possibleValue": ["text/turtle", "application/ld+json"],                            "closedSet": true                        }                        "Content-Length"                    ],                    "expectsHeader": [                        "Authorization",                        {                            "headerName": "Content-Type",                            "possibleValue": ["image/gif", "image/png"],                            "closedSet": true                        }                    ]                }            ],            "supportedProperty": [                {                    "property": "http://api.example.com/vocab#login",                    "writable": true,                    "readable": true,                    "required": true                }            ]        }    ]}
+
+

8. Named instances

+

8.1. hydra:BasicRepresentation

+ + + + + +
Name: + BasicRepresentation +
Summary: + A representation that serializes just the lexical form of a variable value, + but omits language and type information. +
Sub-class of: + VariableRepresentation +
+
+ +
EXAMPLE: hydra:BasicRepresentation
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api/posts",    "@type": "Collection",    "view": {        "@id": "http://api.example.com/api/posts?skip=10",        "@type": "PartialCollectionView",        "first": "http://api.example.com/api/posts",        "last": "http://api.example.com/api/posts?skip=100",        "previous": "http://api.example.com/api/posts",        "next": "http://api.example.com/api/posts?skip=20",        "totalItems": 10,    },    "totalItems": 100,    "member": [        { "@id": "http://api.example.com/api/posts/10" },        { "@id": "http://api.example.com/api/posts/11" },        { "@id": "http://api.example.com/api/posts/12" },        { "@id": "http://api.example.com/api/posts/13" },        { "@id": "http://api.example.com/api/posts/14" },        { "@id": "http://api.example.com/api/posts/15" },        { "@id": "http://api.example.com/api/posts/16" },        { "@id": "http://api.example.com/api/posts/17" },        { "@id": "http://api.example.com/api/posts/18" },        { "@id": "http://api.example.com/api/posts/19" }    ],    "search": {        "template": "/api/posts{?search}",        "resolveRelativeUsing": "hydra:Rfc3986",        "mapping": [            {                "variable": "search",                "property": "hydra:freetextQuery",                "required": true,                "variableRepresentation": "hydra:BasicRepresentation"            }        ]    }}
+
+

8.2. hydra:ExplicitRepresentation

+ + + + + +
Name: + ExplicitRepresentation +
Summary: + A representation that serializes a variable value including its language + and type information and thus differentiating between IRIs and literals. +
Sub-class of: + VariableRepresentation +
+
+ +
EXAMPLE: hydra:ExplicitRepresentation
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api/posts",    "@type": "Collection",    "view": {        "@id": "http://api.example.com/api/posts?skip=10",        "@type": "PartialCollectionView",        "first": "http://api.example.com/api/posts",        "last": "http://api.example.com/api/posts?skip=100",        "previous": "http://api.example.com/api/posts",        "next": "http://api.example.com/api/posts?skip=20",        "totalItems": 10,    },    "totalItems": 100,    "member": [        { "@id": "http://api.example.com/api/posts/10" },        { "@id": "http://api.example.com/api/posts/11" },        { "@id": "http://api.example.com/api/posts/12" },        { "@id": "http://api.example.com/api/posts/13" },        { "@id": "http://api.example.com/api/posts/14" },        { "@id": "http://api.example.com/api/posts/15" },        { "@id": "http://api.example.com/api/posts/16" },        { "@id": "http://api.example.com/api/posts/17" },        { "@id": "http://api.example.com/api/posts/18" },        { "@id": "http://api.example.com/api/posts/19" }    ],    "search": {        "template": "/api/posts{?search}",        "resolveRelativeUsing": "hydra:Rfc3986",        "mapping": [            {                "variable": "search",                "property": "hydra:freetextQuery",                "required": true,                "variableRepresentation": "hydra:ExplicitRepresentation"            }        ]    }}
+
+

8.3. hydra:LinkContext

+ + + + + +
Name: + LinkContext +
Summary: + States that the link’s context IRI, as defined in RFC 5988, should be used + as the base Uri. +
Sub-class of: + BaseUriSource +
+
+ +
EXAMPLE: hydra:LinkContext
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api/posts",    "@type": "Collection",    "view": {        "@id": "http://api.example.com/api/posts?skip=10",        "@type": "PartialCollectionView",        "first": "http://api.example.com/api/posts",        "last": "http://api.example.com/api/posts?skip=100",        "previous": "http://api.example.com/api/posts",        "next": "http://api.example.com/api/posts?skip=20",        "totalItems": 10,    },    "totalItems": 100,    "member": [        { "@id": "http://api.example.com/api/posts/10" },        { "@id": "http://api.example.com/api/posts/11" },        { "@id": "http://api.example.com/api/posts/12" },        { "@id": "http://api.example.com/api/posts/13" },        { "@id": "http://api.example.com/api/posts/14" },        { "@id": "http://api.example.com/api/posts/15" },        { "@id": "http://api.example.com/api/posts/16" },        { "@id": "http://api.example.com/api/posts/17" },        { "@id": "http://api.example.com/api/posts/18" },        { "@id": "http://api.example.com/api/posts/19" }    ],    "search": {        "template": {            "@value": "/api/posts{?search}",            "@type": "hydra:Rfc6570Template"        },        "resolveRelativeUsing": "hydra:LinkContext",        "mapping": [            {                "variable": "search",                "property": "hydra:freetextQuery",                "required": true,                "variableRepresentation": "hydra:BasicRepresentation"            }        ]    }}
+
+

8.4. hydra:Rfc3986

+ + + + + +
Name: + Rfc3986 +
Summary: + States that the link’s context IRI, as defined in RFC 5988, should be used + as the base Uri. +
Sub-class of: + BaseUriSource +
+
+ +
EXAMPLE: hydra:LinkContext
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api/posts",    "@type": "Collection",    "view": {        "@id": "http://api.example.com/api/posts?skip=10",        "@type": "PartialCollectionView",        "first": "http://api.example.com/api/posts",        "last": "http://api.example.com/api/posts?skip=100",        "previous": "http://api.example.com/api/posts",        "next": "http://api.example.com/api/posts?skip=20",        "totalItems": 10,    },    "totalItems": 100,    "member": [        { "@id": "http://api.example.com/api/posts/10" },        { "@id": "http://api.example.com/api/posts/11" },        { "@id": "http://api.example.com/api/posts/12" },        { "@id": "http://api.example.com/api/posts/13" },        { "@id": "http://api.example.com/api/posts/14" },        { "@id": "http://api.example.com/api/posts/15" },        { "@id": "http://api.example.com/api/posts/16" },        { "@id": "http://api.example.com/api/posts/17" },        { "@id": "http://api.example.com/api/posts/18" },        { "@id": "http://api.example.com/api/posts/19" }    ],    "search": {        "template": {            "@value": "/api/posts{?search}",            "@type": "hydra:Rfc6570Template"        },        "resolveRelativeUsing": "hydra:Rfc3986",        "mapping": [            {                "variable": "search",                "property": "hydra:freetextQuery",                "required": true,                "variableRepresentation": "hydra:BasicRepresentation"            }        ]    }}
+
+

9. Data types

+

9.1. hydra:Rfc6570Template

+ + + + +
Name: + Rfc6570Template +
Summary: + An IRI template as defined by [RFC6570]. +
+
+ +
EXAMPLE: hydra:Rfc6570Template
+
{    "@context": "http://www.w3.org/ns/hydra/context.jsonld",    "@id": "http://api.example.com/api/posts",    "@type": "Collection",    "view": {        "@id": "http://api.example.com/api/posts?skip=10",        "@type": "PartialCollectionView",        "first": "http://api.example.com/api/posts",        "last": "http://api.example.com/api/posts?skip=100",        "previous": "http://api.example.com/api/posts",        "next": "http://api.example.com/api/posts?skip=20",        "totalItems": 10,    },    "totalItems": 100,    "member": [        { "@id": "http://api.example.com/api/posts/10" },        { "@id": "http://api.example.com/api/posts/11" },        { "@id": "http://api.example.com/api/posts/12" },        { "@id": "http://api.example.com/api/posts/13" },        { "@id": "http://api.example.com/api/posts/14" },        { "@id": "http://api.example.com/api/posts/15" },        { "@id": "http://api.example.com/api/posts/16" },        { "@id": "http://api.example.com/api/posts/17" },        { "@id": "http://api.example.com/api/posts/18" },        { "@id": "http://api.example.com/api/posts/19" }    ],    "search": {        "template": {            "@value": "/api/posts{?search,limit,offset}",            "@type": "hydra:Rfc6570Template"        },        "resolveRelativeUsing": "hydra:Rfc3986",        "mapping": [            {                "variable": "search",                "property": "hydra:freetextQuery",                "required": true,                "variableRepresentation": "hydra:BasicRepresentation""            },            {                "variable": "limit",                "property": "hydra:limit",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation""            },            {                "variable": "offset",                "property": "hydra:offset",                "required": false,                "variableRepresentation": "hydra:BasicRepresentation""            }        ]    }}
+
+

10. Acknowledgements

+

Note: This section is non-normative.

+

The authors would like to thank the following individuals for contributing +their ideas and providing feedback for writing this specification: +Arnau Siches, elf Pavlik, Karol Szczepański, Mark Baker, Martijn Faassen, +Matthias Lehmann, Ruben Verborgh, Ryan J. McDonough, Sam Goto, +Thomas Hoppe, Tomasz Pluskiewicz, @wasabiwimp (on GitHub).

+

11. The Hydra in JSON-LD

+

Note: This section is non-normative.

+
{  "@context": {    "hydra": "http://www.w3.org/ns/hydra/core#",    "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",    "rdfs": "http://www.w3.org/2000/01/rdf-schema#",    "xsd": "http://www.w3.org/2001/XMLSchema#",    "owl": "http://www.w3.org/2002/07/owl#",    "vs": "http://www.w3.org/2003/06/sw-vocab-status/ns#",    "dc": "http://purl.org/dc/terms/",    "cc": "http://creativecommons.org/ns#",    "schema": "http://schema.org/",    "apiDocumentation": "hydra:apiDocumentation",    "ApiDocumentation": "hydra:ApiDocumentation",    "title": "hydra:title",    "description": "hydra:description",    "entrypoint": { "@id": "hydra:entrypoint", "@type": "@id" },    "supportedClass": { "@id": "hydra:supportedClass", "@type": "@vocab" },    "Class": "hydra:Class",    "supportedProperty": { "@id": "hydra:supportedProperty", "@type": "@id" },    "SupportedProperty": "hydra:SupportedProperty",    "property": { "@id": "hydra:property", "@type": "@vocab" },    "required": "hydra:required",    "readable": "hydra:readable",    "writable": "hydra:writable",    "writeable": "hydra:writeable",    "supportedOperation": { "@id": "hydra:supportedOperation", "@type": "@id" },    "Operation": "hydra:Operation",    "method": "hydra:method",    "expects": { "@id": "hydra:expects", "@type": "@vocab" },    "returns": { "@id": "hydra:returns", "@type": "@vocab" },    "possibleStatus": { "@id": "hydra:possibleStatus", "@type": "@id" },    "Status": "hydra:Status",    "statusCode": "hydra:statusCode",    "Error": "hydra:Error",    "Resource": "hydra:Resource",    "operation": "hydra:operation",    "Collection": "hydra:Collection",    "collection": "hydra:collection",    "member": { "@id": "hydra:member", "@type": "@id" },    "memberAssertion": "hydra:memberAssertion",    "manages": "hydra:manages",    "subject": { "@id": "hydra:subject", "@type": "@vocab" },    "object": { "@id": "hydra:object", "@type": "@vocab" },    "search": "hydra:search",    "freetextQuery": "hydra:freetextQuery",    "view": { "@id": "hydra:view", "@type": "@id" },    "PartialCollectionView": "hydra:PartialCollectionView",    "totalItems": "hydra:totalItems",    "first": { "@id": "hydra:first", "@type": "@id" },    "last": { "@id": "hydra:last", "@type": "@id" },    "next": { "@id": "hydra:next", "@type": "@id" },    "previous": { "@id": "hydra:previous", "@type": "@id" },    "Link": "hydra:Link",    "TemplatedLink": "hydra:TemplatedLink",    "IriTemplate": "hydra:IriTemplate",    "template": "hydra:template",    "Rfc6570Template": "hydra:Rfc6570Template",    "variableRepresentation": { "@id": "hydra:variableRepresentation", "@type": "@vocab" },    "VariableRepresentation": "hydra:VariableRepresentation",    "BasicRepresentation": "hydra:BasicRepresentation",    "ExplicitRepresentation": "hydra:ExplicitRepresentation",    "mapping": "hydra:mapping",    "IriTemplateMapping": "hydra:IriTemplateMapping",    "variable": "hydra:variable",    "offset": { "@id": "hydra:offset", "@type": "xsd:nonNegativeInteger" },    "limit": { "@id": "hydra:limit", "@type": "xsd:nonNegativeInteger" },    "pageIndex": { "@id": "hydra:pageIndex", "@type": "xsd:nonNegativeInteger" },    "pageReference": { "@id": "hydra:pageReference" },    "returnsHeader": { "@id": "hydra:returnsHeader", "@type": "xsd:string" },    "expectsHeader": { "@id": "hydra:expectsHeader", "@type": "xsd:string" },    "HeaderSpecification": "hydra:HeaderSpecification",    "headerName": "hydra:headerName",    "possibleValue": "hydra:possibleValue",    "closedSet": { "@id": "hydra:possibleValue", "@type": "xsd:boolean" },    "name": { "@id": "hydra:name", "@type": "xsd:string" },    "extension": { "@id": "hydra:extension", "@type": "@id" },    "isDefinedBy": { "@id": "rdfs:isDefinedBy", "@type": "@id" },    "defines": { "@reverse": "rdfs:isDefinedBy" },    "comment": "rdfs:comment",    "label": "rdfs:label",    "preferredPrefix": "http://purl.org/vocab/vann/preferredNamespacePrefix",    "cc:license": {"@type": "@id" },    "cc:attributionURL": {"@type": "@id" },    "domain": { "@id": "rdfs:domain", "@type": "@vocab" },    "range": {"@id": "rdfs:range", "@type": "@vocab" },    "subClassOf": { "@id": "rdfs:subClassOf", "@type": "@vocab" },    "subPropertyOf": { "@id": "rdfs:subPropertyOf", "@type": "@vocab" },    "seeAlso": { "@id": "rdfs:seeAlso", "@type": "@id" },    "domainIncludes": { "@id": "schema:domainIncludes", "@type": "@id" },    "rangeIncludes": { "@id": "schema:rangeIncludes", "@type": "@id" }  },  "@id": "http://www.w3.org/ns/hydra/core",  "@type": "owl:Ontology",  "label": "The Hydra Core Vocabulary",  "comment": "A lightweight vocabulary for hypermedia-driven Web APIs.",  "seeAlso": "https://www.hydra-cg.com/spec/latest/core/",  "preferredPrefix": "hydra",  "dc:description": "The Hydra Core Vocabulary is a lightweight vocabulary to create hypermedia-driven Web APIs. By specifying a number of concepts commonly used in Web APIs it enables the creation of generic API clients.",  "dc:rights": "Copyright © 2012-2014 the Contributors to the Hydra Core Vocabulary Specification",  "dc:publisher": "Hydra W3C Community Group",  "cc:license": "http://creativecommons.org/licenses/by/4.0/",  "cc:attributionName": "Hydra W3C Community Group",  "cc:attributionURL": "http://www.hydra-cg.com/",  "defines": [    {      "@id": "hydra:Resource",      "@type": "hydra:Class",      "label": "Hydra Resource",      "comment": "The class of dereferenceable resources by means a client can attempt to dereference; however, the received responses should still be verified.",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:Class",      "@type": [ "hydra:Resource", "rdfs:Class" ],      "subClassOf": [ "rdfs:Class" ],      "label": "Hydra Class",      "comment": "The class of Hydra classes.",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:Link",      "@type": "hydra:Class",      "subClassOf": [ "hydra:Resource", "rdf:Property" ],      "label": "Link",      "comment": "The class of properties representing links.",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:apiDocumentation",      "@type": "hydra:Link",      "label": "apiDocumentation",      "comment": "A link to the API documentation.",      "range": "hydra:ApiDocumentation",      "domain": "hydra:Resource",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:ApiDocumentation",      "@type": "hydra:Class",      "subClassOf": "hydra:Resource",      "label": "ApiDocumentation",      "comment": "The Hydra API documentation class.",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:entrypoint",      "@type": "hydra:Link",      "label": "entrypoint",      "comment": "A link to main entry point of the Web API.",      "domain": "hydra:ApiDocumentation",      "range": "hydra:Resource",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:supportedClass",      "@type": "hydra:Link",      "label": "supported classes",      "comment": "A class known to be supported by the Web API.",      "domain": "hydra:ApiDocumentation",      "range": "rdfs:Class",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:possibleStatus",      "@type": "hydra:Link",      "label": "possible status",      "comment": "A status that might be returned by the Web API (other statuses should be expected and properly handled as well).",      "range": "hydra:Status",      "domainIncludes": ["hydra:ApiDocumentation", "hydra:Operation"],      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:supportedProperty",      "@type": "hydra:Link",      "label": "supported properties",      "comment": "The properties known to be supported by a Hydra class.",      "domain": "rdfs:Class",      "range": "hydra:SupportedProperty",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:SupportedProperty",      "@type": "hydra:Class",      "label": "Supported Property",      "comment": "A property known to be supported by a Hydra class.",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:property",      "@type": "rdf:Property",      "label": "property",      "comment": "A property.",      "range": "rdf:Property",      "domainIncludes": ["hydra:SupportedProperty", "hydra:IriTemplateMapping"],      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:required",      "@type": "rdf:Property",      "label": "required",      "comment": "True if the property is required, false otherwise.",      "range": "xsd:boolean",      "domainIncludes": ["hydra:SupportedProperty", "hydra:IriTemplateMapping"],      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:readable",      "@type": "rdf:Property",      "label": "readable",      "comment": "True if the client can retrieve the property's value, false otherwise.",      "domain": "hydra:SupportedProperty",      "range": "xsd:boolean",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:writable",      "@type": "rdf:Property",      "label": "writable",      "comment": "True if the client can change the property's value, false otherwise.",      "domain": "hydra:SupportedProperty",      "range": "xsd:boolean",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:writeable",      "subPropertyOf": "hydra:writable",      "label": "writable",      "comment": "This property is left for compatibility purposes and hydra:writable should be used instead.",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "archaic"    },    {      "@id": "hydra:supportedOperation",      "@type": "hydra:Link",      "label": "supported operation",      "comment": "An operation supported by instances of the specific Hydra class, or the target of the Hydra link, or Iri template.",      "range": "hydra:Operation",      "domainIncludes": ["rdfs:Class", "hydra:Class", "hydra:Link", "hydra:TemplatedLink", "hydra:SupportedProperty"],      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:operation",      "@type": "hydra:Link",      "label": "operation",      "comment": "An operation supported by the Hydra resource.",      "domain": "hydra:Resource",      "range": "hydra:Operation",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:Operation",      "@type": "hydra:Class",      "label": "Operation",      "comment": "An operation.",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:method",      "@type": "rdf:Property",      "label": "method",      "comment": "The protocol method.",      "domain": "hydra:Operation",      "range": "xsd:string",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:expects",      "@type": "hydra:Link",      "label": "expects",      "comment": "The information expected by the Web API.",      "domain": "hydra:Operation",      "rangeIncludes": ["rdfs:Resource", "hydra:Resource", "rdfs:Class", "hydra:Class"],      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:returns",      "@type": "hydra:Link",      "label": "returns",      "comment": "The information returned by the Web API on success.",      "domain": "hydra:Operation",      "rangeIncludes": ["rdfs:Resource", "hydra:Resource", "rdfs:Class", "hydra:Class"],      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:Status",      "@type": "hydra:Class",      "label": "Status code description",      "comment": "Additional information about a status code that might be returned.",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:statusCode",      "@type": "rdf:Property",      "label": "status code",      "comment": "The response status code. Please note it may happen this value will be different to actual status code received.",      "domain": "hydra:Status",      "range": "xsd:integer",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:title",      "@type": "rdf:Property",      "subPropertyOf": "rdfs:label",      "label": "title",      "comment": "A title, often used along with a description.",      "range": "xsd:string",      "domainIncludes": [        "hydra:ApiDocumentation",        "hydra:Status",        "hydra:Class",        "hydra:SupportedProperty",        "hydra:Operation",        "hydra:Link",        "hydra:TemplatedLink"      ],      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:description",      "@type": "rdf:Property",      "subPropertyOf": "rdfs:comment",      "label": "description",      "comment": "A description.",      "range": "xsd:string",      "domainIncludes": [        "hydra:ApiDocumentation",        "hydra:Status",        "hydra:Class",        "hydra:SupportedProperty",        "hydra:Operation",        "hydra:Link",        "hydra:TemplatedLink"      ],      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:Error",      "@type": "hydra:Class",      "subClassOf": "hydra:Status",      "label": "Error",      "comment": "A runtime error, used to report information beyond the returned status code.",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:Collection",      "@type": "hydra:Class",      "subClassOf": "hydra:Resource",      "label": "Collection",      "comment": "A collection holding references to a number of related resources.",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:collection",      "@type": "hydra:Link",      "label": "collection",      "comment": "Collections somehow related to this resource.",      "range": "hydra:Collection",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:memberAssertion",      "label": "member assertion",      "comment": "Semantics of each member provided by the collection.",      "domainIncludes": ["hydra:Collection", "hydra:Class"],      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:manages",      "subPropertyOf": "hydra:memberAssertion",      "label": "manages",      "comment": "This predicate is left for compatibility purposes and hydra:memberAssertion should be used instead.",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "archaic"    },    {      "@id": "hydra:subject",      "label": "subject",      "comment": "The subject.",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:object",      "label": "object",      "comment": "The object.",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:member",      "@type": "hydra:Link",      "label": "member",      "comment": "A member of the collection.",      "domain": "hydra:Collection",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:view",      "@type": "hydra:Link",      "label": "view",      "comment": "A specific view of a resource.",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:PartialCollectionView",      "@type": "hydra:Class",      "subClassOf": "hydra:Resource",      "label": "PartialCollectionView",      "comment": "A PartialCollectionView describes a partial view of a Collection. Multiple PartialCollectionViews can be connected with the next/previous properties to allow a client to retrieve all members of the collection.",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:totalItems",      "@type": "rdf:Property",      "label": "total items",      "comment": "The total number of items referenced by a collection.",      "domain": "hydra:Collection",      "range": "xsd:integer",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:first",      "@type": "hydra:Link",      "label": "first",      "comment": "The first resource of an interlinked set of resources.",      "domain": "hydra:Resource",      "range": "hydra:Resource",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:last",      "@type": "hydra:Link",      "label": "last",      "comment": "The last resource of an interlinked set of resources.",      "domain": "hydra:Resource",      "range": "hydra:Resource",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:next",      "@type": "hydra:Link",      "label": "next",      "comment": "The resource following the current instance in an interlinked set of resources.",      "domain": "hydra:Resource",      "range": "hydra:Resource",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:previous",      "@type": "hydra:Link",      "label": "previous",      "comment": "The resource preceding the current instance in an interlinked set of resources.",      "domain": "hydra:Resource",      "range": "hydra:Resource",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:search",      "@type": "hydra:TemplatedLink",      "label": "search",      "comment": "A Iri template that can be used to query a collection.",      "range": "hydra:IriTemplate",      "domain": "hydra:Resource",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:freetextQuery",      "@type": "rdf:Property",      "label": "freetext query",      "comment": "A property representing a freetext query.",      "range": "xsd:string",      "domain": "hydra:Resource",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:TemplatedLink",      "@type": "hydra:Class",      "subClassOf": [ "hydra:Resource", "rdf:Property" ],      "label": "Templated Link",      "comment": "A templated link.",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:IriTemplate",      "@type": "hydra:Class",      "label": "IRI Template",      "comment": "The class of IRI templates.",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:template",      "@type": "rdf:Property",      "label": "template",      "comment": "A templated string with placeholders. The literal's datatype indicates the template syntax; if not specified, hydra:Rfc6570Template is assumed.",      "seeAlso": "hydra:Rfc6570Template",      "domain": "hydra:IriTemplate",      "range": "hydra:Rfc6570Template",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:Rfc6570Template",      "@type": "rdfs:Datatype",      "label": "RFC6570 IRI template",      "comment": "An IRI template as defined by RFC6570.",      "seeAlso": "http://tools.ietf.org/html/rfc6570",      "range": "xsd:string",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:variableRepresentation",      "@type": "rdf:Property",      "label": "variable representation",      "comment": "The representation format to use when expanding the Iri template.",      "range": "hydra:VariableRepresentation",      "domain": "hydra:IriTemplateMapping",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:VariableRepresentation",      "@type": "hydra:Class",      "label": "VariableRepresentation",      "comment": "A representation specifies how to serialize variable values into strings.",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:BasicRepresentation",      "@type": "hydra:VariableRepresentation",      "label": "BasicRepresentation",      "comment": "A representation that serializes just the lexical form of a variable value, but omits language and type information.",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:ExplicitRepresentation",      "@type": "hydra:VariableRepresentation",      "label": "ExplicitRepresentation",      "comment": "A representation that serializes a variable value including its language and type information and thus differentiating between IRIs and literals.",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:mapping",      "@type": "rdf:Property",      "label": "mapping",      "comment": "A variable-to-property mapping of the IRI template.",      "domain": "hydra:IriTemplate",      "range": "hydra:IriTemplateMapping",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:IriTemplateMapping",      "@type": "hydra:Class",      "label": "IriTemplateMapping",      "comment": "A mapping from an IRI template variable to a property.",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:variable",      "@type": "rdf:Property",      "label": "variable",      "comment": "An Iri template variable.",      "domain": "hydra:IriTemplateMapping",      "range": "xsd:string",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:resolveRelativeUsing",      "@type": "rdf:Property",      "label": "relative Uri resolution",      "comment": "Instructs on how to resolve relative Uri created by the Iri template resolution.",      "domain": "hydra:IriTemplate",      "range": "hydra:BaseUriSource",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:BaseUriSource",      "@type": "hydra:Class",      "subClassOf": "hydra:Resource",      "label": "Base Uri source",      "comment": "Provides a base abstract for base Uri source for Iri template resolution.",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:Rfc3986",      "@type": "hydra:BaseUriSource",      "label": "RFC 3986 based",      "comment": "States that the base Uri should be established using RFC 3986 reference resolution algorithm specified in section 5.",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:LinkContext",      "@type": "hydra:BaseUriSource",      "label": "Link context",      "comment": "States that the link's context IRI, as defined in RFC 5988, should be used as the base Uri.",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:offset",      "@type": "rdf:Property",      "label": "skip",      "comment": "Instructs to skip N elements of the set.",      "range": "xsd:nonNegativeInteger",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:limit",      "@type": "rdf:Property",      "label": "take",      "comment": "Instructs to limit set only to N elements.",      "range": "xsd:nonNegativeInteger",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:pageIndex",      "@type": "rdf:Property",      "subPropertyOf": "hydra:pageReference",      "label": "page index",      "comment": "Instructs to provide a specific page of the collection at a given index.",      "range": "xsd:nonNegativeInteger",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:pageReference",      "@type": "rdf:Property",      "label": "page reference",      "comment": "Instructs to provide a specific page reference of the collection.",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:returnsHeader",      "@type": "rdf:Property",      "label": "returns header",      "comment": "Name of the header returned by the operation.",      "domain": "hydra:Operation",      "rangeIncludes": ["xsd:string", "hydra:HeaderSpecification"],      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:expectsHeader",      "@type": "rdf:Property",      "label": "expects header",      "comment": "Specification of the header expected by the operation.",      "domain": "hydra:Operation",      "rangeIncludes": ["xsd:string", "hydra:HeaderSpecification"],      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:HeaderSpecification",      "@type": "rdfs:Class",      "subClassOf": "hydra:Resource",      "label": "Header specification",      "comment": "Specifies a possible either expected or returned header values.",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:headerName",      "@type": "rdf:Property",      "label": "header name",      "comment": "Name of the header.",      "domain": "hydra:HeaderSpecification",      "range": "xsd:string",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:possibleValue",      "@type": "rdf:Property",      "label": "possible header value",      "comment": "Possible value of the header.",      "domain": "hydra:HeaderSpecification",      "range": "xsd:string",      "vs:term_status": "testing"    },    {      "@id": "hydra:closedSet",      "@type": "rdf:Property",      "label": "closed set",      "comment": "Determines whether the provided set of header values is closed or not.",      "domain": "hydra:HeaderSpecification",      "range": "xsd:boolean",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    },    {      "@id": "hydra:extension",      "@type": "rdf:Property",      "label": "extension",      "comment": "Hint on what kind of extensions are in use.",      "domain": "hydra:ApiDocumentation",      "isDefinedBy": "http://www.w3.org/ns/hydra/core",      "vs:term_status": "testing"    }  ]}
+

12. The Hydra error context

+

Note: This section is non-normative.

+
{  "@context": {    "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",    "rdfs": "http://www.w3.org/2000/01/rdf-schema#",    "hydra": "http://www.w3.org/ns/hydra/core#",    "type": { "@id": "rdf:type", "@type": "@id" },    "title": "rdfs:label",    "detail": "rdfs:comment",    "status": "hydra:statusCode",    "instance": { "@id": "rdfs:seeAlso", "@type": "@id" }  }}
+
+
+

Conformance

+

Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. + The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” + in the normative parts of this document + are to be interpreted as described in RFC 2119. + However, for readability, + these words do not appear in all uppercase letters in this specification.

+

All of the text of this specification is normative + except sections explicitly marked as non-normative, examples, and notes. [RFC2119]

+

Examples in this specification are introduced with the words “for example” + or are set apart from the normative text with class="example", like this:

+
This is an example of an informative example.
+

Informative notes begin with the word “Note” + and are set apart from the normative text with class="note", like this:

+

Note, this is an informative note.

+
+ +

Index

+

Terms defined by this specification

+ +

References

+

Normative References

+
+
[BCP47] +
A. Phillips, Ed.; M. Davis, Ed.. Tags for Identifying Languages. September 2009. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc5646 +
[HydraCG] +
Hydra W3C Community Group. URL: https://www.w3.org/community/hydra/ +
[RDF-Schema] +
Dan Brickley; Ramanathan Guha. RDF Schema 1.1. 25 February 2014. REC. URL: https://www.w3.org/TR/rdf-schema/ +
[RFC2119] +
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119 +
[RFC3986] +
T. Berners-Lee; R. Fielding; L. Masinter. Uniform Resource Identifier (URI): Generic Syntax. January 2005. Internet Standard. URL: https://datatracker.ietf.org/doc/html/rfc3986 +
[RFC6570] +
J. Gregorio; et al. URI Template. March 2012. Proposed Standard. URL: https://datatracker.ietf.org/doc/html/rfc6570 +
[RFC7240] +
J. Snell. Prefer Header for HTTP. June 2014. Proposed Standard. URL: https://datatracker.ietf.org/doc/html/rfc7240 +
[RFC7807] +
M. Nottingham; E. Wilde. Problem Details for HTTP APIs. March 2016. Proposed Standard. URL: https://datatracker.ietf.org/doc/html/rfc7807 +
[RFC8288] +
M. Nottingham. Web Linking. October 2017. Proposed Standard. URL: https://httpwg.org/specs/rfc8288.html +
[Turtle] +
Eric Prud'hommeaux; Gavin Carothers. RDF 1.1 Turtle. 25 February 2014. REC. URL: https://www.w3.org/TR/turtle/ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spec/latest/core/vocabulary.png b/spec/latest/core/vocabulary.png index 805b042bd24c82de42121680160725195ff20042..bf31647aa71761725a8b3be9bbb11911fbf0a88a 100644 GIT binary patch literal 122000 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 Lt~yE0GWh=h7Y7`Q literal 22555 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 From 4aa5cba3bbf21fbe05165c7c2fdf904464539f98 Mon Sep 17 00:00:00 2001 From: alien-mcl Date: Sun, 11 Dec 2022 20:29:48 +0100 Subject: [PATCH 5/9] Added latest changes from the main branch --- spec/latest/core/core.jsonld | 45 +- spec/latest/core/index.bs | 301 +++++++++++-- spec/latest/core/index.html | 821 +++++++++++++++++++++-------------- 3 files changed, 797 insertions(+), 370 deletions(-) diff --git a/spec/latest/core/core.jsonld b/spec/latest/core/core.jsonld index 1331821..a680e46 100644 --- a/spec/latest/core/core.jsonld +++ b/spec/latest/core/core.jsonld @@ -28,6 +28,7 @@ "method": "hydra:method", "expects": { "@id": "hydra:expects", "@type": "@vocab" }, "returns": { "@id": "hydra:returns", "@type": "@vocab" }, + "availability": { "@id": "hydra:availability", "@type": "@vocab" }, "possibleStatus": { "@id": "hydra:possibleStatus", "@type": "@id" }, "Status": "hydra:Status", "statusCode": "hydra:statusCode", @@ -167,6 +168,48 @@ "isDefinedBy": "http://www.w3.org/ns/hydra/core", "vs:term_status": "testing" }, + { + "@id": "hydra:availability", + "@type": "rdf:Property", + "label": "availability", + "comment": "Availability of the operation explicitely stated.", + "range": "hydra:Availability", + "domain": "hydra:Operation", + "isDefinedBy": "http://www.w3.org/ns/hydra/core", + "vs:term_status": "testing" + }, + { + "@id": "hydra:Availability", + "@type": "hydra:Class", + "label": "Availability", + "comment": "Availability states when the operation can be invoked.", + "isDefinedBy": "http://www.w3.org/ns/hydra/core", + "vs:term_status": "testing" + }, + { + "@id": "hydra:Unavailable", + "@type": "hydra:Availability", + "label": "Unavailable", + "comment": "States an operation previously announced is unavailable in current circumstances.", + "isDefinedBy": "http://www.w3.org/ns/hydra/core", + "vs:term_status": "testing" + }, + { + "@id": "hydra:Unauthorized", + "@type": "hydra:Availability", + "label": "Unauthorized", + "comment": "States an operation previously announced should not be invoked as the current user is not authorized to invoke it.", + "isDefinedBy": "http://www.w3.org/ns/hydra/core", + "vs:term_status": "testing" + }, + { + "@id": "hydra:Available", + "@type": "hydra:Availability", + "label": "Available", + "comment": "States an operation is available for invocation. This is a default operation availability.", + "isDefinedBy": "http://www.w3.org/ns/hydra/core", + "vs:term_status": "testing" + }, { "@id": "hydra:possibleStatus", "@type": "hydra:Link", @@ -554,7 +597,7 @@ "label": "variable representation", "comment": "The representation format to use when expanding the Iri template.", "range": "hydra:VariableRepresentation", - "domain": "hydra:IriTemplateMapping", + "domainIncludes": ["hydra:IriTemplateMapping", "hydra:IriTemplate"], "isDefinedBy": "http://www.w3.org/ns/hydra/core", "vs:term_status": "testing" }, diff --git a/spec/latest/core/index.bs b/spec/latest/core/index.bs index 549fbb6..88d910d 100644 --- a/spec/latest/core/index.bs +++ b/spec/latest/core/index.bs @@ -648,6 +648,79 @@ Direct usage of [=supportedOperation=] on *rdf:Property* without elevating it to the [=Link=] SHOULD NOT be implemented as clients may not discover such a construct correctly. +There are rare situations when some supported operations once announced in the +API documentation should be retracted, i.e. to reflect current state of the +application or current user capabilities (or lack of them). It is doable +with the [=availability=] predicate that can be added to the [=Operation=] +itself. By default all operations are [=Available=] without limits and it +is up for the server to change that, and for the client to discover any +discrepancies compared against the API documentation in the runtime. Yet +server may want to inform the client that at the very moment an operation is either +[=Unavailable=] or Unauthorized. The latter MAY be used to notify +client that the user used to invoke the request that provides operation +availability information is currently not authorized for that very operation +to be invoked. The former on the other hand MAY be used to inform that +the operation is currently unavailable and client SHOULD NOT invoke it. +Server MAY also provide more custom reasons for which the operation is not +available but it SHOULD provide at least one of the _Hydra_ built in reasons. + +Usage of the [=availability=] is restricted only to the [=Operation=]s +and MUST NOT be used on [=SupportedOperation=]s. The [=availability=] +predicate also MUST take precedence over a supported operation declaration. +The operation that comes with [=availability=] predicate SHOULD be identified +using any of the below enlisted methods: + +- Iri +- exact match of a resource described by [=possibleStatus=], [=method=], + [=expects=], [=returns=] or combination of those. + +
+
+{
+	"@context": "http://www.w3.org/ns/hydra/context.jsonld",
+	"@id": "http://api.example.com/doc/#comments",
+	"@type": "Link",
+	"supportedOperation": [
+		{
+			"@type": "Operation",
+			"method": "POST",
+			"expects": "http://api.example.com/doc/#Upload"
+		},
+		{
+			"@type": "Operation",
+			"method": "POST",
+			"expects": "http://api.example.com/doc/#Comment"
+		}
+	]
+}
+
+
+
+
+{
+	"@context": "http://www.w3.org/ns/hydra/context.jsonld",
+	"@id": "http://api.example.com/doc/",
+	"@type": "Collection",
+	"operation": [
+		{
+			"@type": "Operation",
+			"method": "POST",
+			"expects": "http://api.example.com/doc/#Upload",
+			"availability": "Unavailable"
+		}
+	]
+}
+
+
+ +In the example above the operation that expects an uploaded file became +[=Unavailable=], while the one expecting a comment remains available as +the [=expects=] predicate does not match any supported operations. +It is still recommended to mark operations being subject for further +restrictions with an Iri as from the client perspective this may be +easier to implement simple literal Iri comparison rather than to compare +graphs of objects. + Note: These are the simple example scenarios and possible usages are not limited to those described above. @@ -1103,6 +1176,43 @@ representations as well as the result of expanding the IRI template +The example Description of an IRI Template that was already mentioned +uses a [=variableRepresentation=] on the whole [=IriTemplate=], but +each mapped variable represented as an [=riTemplateMapping=] can have +its own [=ariableRepresentation=] declaration. It MUST override +the declaration from the [=IriTemplate=] level for that very +[=IriTemplateMapping=] as it takes precedence. The example below +depicts such a situation: + +
+
+{
+	"@context": "http://www.w3.org/ns/hydra/context.jsonld",
+	"@type": "IriTemplate",
+	"template": "http://api.example.com/issues{?q,category}",
+	"variableRepresentation": "ExplicitRepresentation",
+	"mapping": [
+		{
+			"@type": "IriTemplateMapping",
+			"variable": "q",
+			"property": "hydra:freetextQuery",
+			"variableRepresentation": "BasicRepresentation",
+			"required": true
+		},
+		{
+			"@type": "IriTemplateMapping",
+			"variable": "category",
+			"property": "schema:category"
+		}
+	]
+}
+
+
+ +In this example, the variable category will be serialised using the explicit representation, +derived from the template itself. The variable q on the other hand will override that +to use basic representation. + Similar to how Hydra's [=Link=] class allows the definition of properties that represent hyperlinks as described in [[#adding-affordances-to-representations]], the [=TemplatedLink=] class @@ -1112,11 +1222,11 @@ can be used to document available search interfaces.
-    {
-        "@context": "http://www.w3.org/ns/hydra/context.jsonld",
-        "@id": "hydra:search",
-        "@type": "hydra:TemplatedLink"
-    }
+{
+	"@context": "http://www.w3.org/ns/hydra/context.jsonld",
+	"@id": "hydra:search",
+	"@type": "hydra:TemplatedLink"
+}
 
@@ -1541,6 +1651,18 @@ Classes {#classes}
+## hydra:Availability ## {#class-Availability} + + + + + + + + + +
Name:Availability
Summary:Availability states when the operation can be invoked.
+ ## hydra:BaseUriSource ## {#class-BaseUriSource} @@ -2247,6 +2369,43 @@ Link: ; rel="http://www.w3.org/ns/hydra/core#apiDoc +## hydra:availability ## {#property-availability} +
+ + + + + + + + + + + + + + + + +
Name:availability‎
Summary:Availability of the operation explicitely stated.
Domain:[=Operation=]
Range:[=Availability=]
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/doc/", + "@type": "Collection", + "operation": [ + { + "@type": "Operation", + "method": "POST", + "expects": "http://api.example.com/doc/#Upload", + "availability": "Unavailable" + } + ] +} + +
+ ## hydra:closedSet ## {#property-closedSet} @@ -5398,8 +5557,8 @@ Link: ; rel="http://www.w3.org/ns/json-ld#cont - - + + @@ -5407,7 +5566,7 @@ Link: ; rel="http://www.w3.org/ns/json-ld#cont
1
Domain:[=IriTemplateMapping=]Domain includes:[=IriTemplateMapping=], [=IriTemplate=]
Range:
- +<xmp highlight="json-ld" line-highlight="30,36"> { "@context": "http://www.w3.org/ns/hydra/context.jsonld", "@id": "http://api.example.com/api/posts", @@ -5437,24 +5596,23 @@ Link: <http://www.w3.org/ns/hydra/error>; rel="http://www.w3.org/ns/json-ld#cont "search": { "template": "/api/posts{?search,limit,offset}", "resolveRelativeUsing": "hydra:Rfc3986", + "variableRepresentation": "hydra:BasicRepresentation", "mapping": [ { "variable": "search", "property": "hydra:freetextQuery", "required": true, - "variableRepresentation": "hydra:BasicRepresentation" + "variableRepresentation": "hydra:ExplicitRepresentation" }, { "variable": "limit", "property": "hydra:limit", - "required": false, - "variableRepresentation": "hydra:BasicRepresentation" + "required": false }, { "variable": "offset", "property": "hydra:offset", - "required": false, - "variableRepresentation": "hydra:BasicRepresentation" + "required": false } ] } @@ -5614,6 +5772,38 @@ Link: <http://www.w3.org/ns/hydra/error>; rel="http://www.w3.org/ns/json-ld#cont Named instances {#named-instances} =============== +## hydra:Available ## {#instance-Available} +<table class="def"> + <tr> + <th>Name:</th> + <td><dfn export id="hydra:Available">Available</dfn></td> + </tr> + <tr> + <th>Summary:</th> + <td> + States an operation is available for invocation. + This is a default operation availability. + </td> + </tr> +</table> +<div class="example" heading="hydra:Available"> +<xmp highlight="json-ld" line-highlight="10"> +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/doc/", + "@type": "Collection", + "operation": [ + { + "@type": "Operation", + "method": "POST", + "expects": "http://api.example.com/doc/#Upload", + "availability": "Available" + } + ] +} + +
+ ## hydra:BasicRepresentation ## {#instance-BasicRepresentation} @@ -5627,10 +5817,6 @@ Named instances {#named-instances} but omits language and type information. - - - -
Sub-class of:[=VariableRepresentation=]
@@ -5689,10 +5875,6 @@ Named instances {#named-instances} and type information and thus differentiating between IRIs and literals. </td> </tr> - <tr> - <th>Sub-class of:</th> - <td>[=VariableRepresentation=]</td> - </tr> </table> <div class="example" heading="hydra:ExplicitRepresentation"> <xmp highlight="json-ld" line-highlight="35"> @@ -5751,10 +5933,6 @@ Named instances {#named-instances} as the base Uri. </td> </tr> - <tr> - <th>Sub-class of:</th> - <td>[=BaseUriSource=]</td> - </tr> </table> <div class="example" heading="hydra:LinkContext"> <xmp highlight="json-ld" line-highlight="32"> @@ -5816,10 +5994,6 @@ Named instances {#named-instances} as the base Uri. </td> </tr> - <tr> - <th>Sub-class of:</th> - <td>[=BaseUriSource=]</td> - </tr> </table> <div class="example" heading="hydra:LinkContext"> <xmp highlight="json-ld" line-highlight="32"> @@ -5868,6 +6042,69 @@ Named instances {#named-instances}
+## hydra:Unauthorized ## {#instance-Unauthorized} + + + + + + + + + +
Name:Unauthorized
Summary: + States an operation previously announced should not be invoked + as the current user is not authorized to invoke it. +
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/doc/", + "@type": "Collection", + "operation": [ + { + "@type": "Operation", + "method": "POST", + "expects": "http://api.example.com/doc/#Upload", + "availability": "Unauthorized" + } + ] +} + +
+ +## hydra:Unavailable ## {#instance-Unavailable} + + + + + + + + + +
Name:Unavailable
Summary: + States an operation previously announced is unavailable in current circumstances. +
+
+ +{ + "@context": "http://www.w3.org/ns/hydra/context.jsonld", + "@id": "http://api.example.com/doc/", + "@type": "Collection", + "operation": [ + { + "@type": "Operation", + "method": "POST", + "expects": "http://api.example.com/doc/#Upload", + "availability": "Unavailable" + } + ] +} + +
+ Data types {#data-types} ========== @@ -5948,9 +6185,11 @@ Note: This section is non-normative. The authors would like to thank the following individuals for contributing their ideas and providing feedback for writing this specification: -Arnau Siches, elf Pavlik, Karol Szczepański, Mark Baker, Martijn Faassen, +Arnau Siches, elf Pavlik, Mark Baker, Martijn Faassen, Matthias Lehmann, Ruben Verborgh, Ryan J. McDonough, Sam Goto, -Thomas Hoppe, Tomasz Pluskiewicz, @wasabiwimp (on GitHub). +Thomas Hoppe, @wasabiwimp (on GitHub). + +Special thanks to Tomasz Pluskiewicz. The Hydra in JSON-LD {#vocab-jsonld} ==================================== diff --git a/spec/latest/core/index.html b/spec/latest/core/index.html index cd7a4fa..a0de7e3 100644 --- a/spec/latest/core/index.html +++ b/spec/latest/core/index.html @@ -2140,7 +2140,7 @@

Hydra Core Vocabulary

-

Living Document,

+

Living Document,

This version: @@ -2156,7 +2156,7 @@

@@ -2201,78 +2201,83 @@

Table of Contents

6 Classes
  1. 6.1 hydra:ApiDocumentation -
  2. 6.2 hydra:BaseUriSource -
  3. 6.3 hydra:Class -
  4. 6.4 hydra:Collection -
  5. 6.5 hydra:Error -
  6. 6.6 hydra:HeaderSpecification -
  7. 6.7 hydra:IriTemplate -
  8. 6.8 hydra:IriTemplateMapping -
  9. 6.9 hydra:Link -
  10. 6.10 hydra:Operation -
  11. 6.11 hydra:PartialCollectionView -
  12. 6.12 hydra:Resource -
  13. 6.13 hydra:Status -
  14. 6.14 hydra:SupportedProperty -
  15. 6.15 hydra:TemplatedLink -
  16. 6.16 hydra:VariableRepresentation +
  17. 6.2 hydra:Availability +
  18. 6.3 hydra:BaseUriSource +
  19. 6.4 hydra:Class +
  20. 6.5 hydra:Collection +
  21. 6.6 hydra:Error +
  22. 6.7 hydra:HeaderSpecification +
  23. 6.8 hydra:IriTemplate +
  24. 6.9 hydra:IriTemplateMapping +
  25. 6.10 hydra:Link +
  26. 6.11 hydra:Operation +
  27. 6.12 hydra:PartialCollectionView +
  28. 6.13 hydra:Resource +
  29. 6.14 hydra:Status +
  30. 6.15 hydra:SupportedProperty +
  31. 6.16 hydra:TemplatedLink +
  32. 6.17 hydra:VariableRepresentation
  • 7 Properties
    1. 7.1 hydra:apiDocumentation -
    2. 7.2 hydra:closedSet -
    3. 7.3 hydra:collection -
    4. 7.4 hydra:description -
    5. 7.5 hydra:entrypoint -
    6. 7.6 hydra:expects -
    7. 7.7 hydra:expectsHeader -
    8. 7.8 hydra:extension -
    9. 7.9 hydra:first -
    10. 7.10 hydra:freetextQuery -
    11. 7.11 hydra:headerName -
    12. 7.12 hydra:last -
    13. 7.13 hydra:limit -
    14. 7.14 hydra:mapping -
    15. 7.15 hydra:member -
    16. 7.16 hydra:memberAssertion -
    17. 7.17 hydra:method -
    18. 7.18 hydra:next -
    19. 7.19 hydra:object -
    20. 7.20 hydra:offset -
    21. 7.21 hydra:operation -
    22. 7.22 hydra:pageIndex -
    23. 7.23 hydra:pageReference -
    24. 7.24 hydra:possibleStatus -
    25. 7.25 hydra:possibleValue -
    26. 7.26 hydra:previous -
    27. 7.27 hydra:property -
    28. 7.28 hydra:readable -
    29. 7.29 hydra:required -
    30. 7.30 hydra:resolveRelativeUsing -
    31. 7.31 hydra:returns -
    32. 7.32 hydra:returnsHeader -
    33. 7.33 hydra:search -
    34. 7.34 hydra:statusCode -
    35. 7.35 hydra:subject -
    36. 7.36 hydra:supportedClass -
    37. 7.37 hydra:supportedOperation -
    38. 7.38 hydra:supportedProperty -
    39. 7.39 hydra:template -
    40. 7.40 hydra:title -
    41. 7.41 hydra:totalItems -
    42. 7.42 hydra:variable -
    43. 7.43 hydra:variableRepresentation -
    44. 7.44 hydra:view -
    45. 7.45 hydra:writable +
    46. 7.2 hydra:availability +
    47. 7.3 hydra:closedSet +
    48. 7.4 hydra:collection +
    49. 7.5 hydra:description +
    50. 7.6 hydra:entrypoint +
    51. 7.7 hydra:expects +
    52. 7.8 hydra:expectsHeader +
    53. 7.9 hydra:extension +
    54. 7.10 hydra:first +
    55. 7.11 hydra:freetextQuery +
    56. 7.12 hydra:headerName +
    57. 7.13 hydra:last +
    58. 7.14 hydra:limit +
    59. 7.15 hydra:mapping +
    60. 7.16 hydra:member +
    61. 7.17 hydra:memberAssertion +
    62. 7.18 hydra:method +
    63. 7.19 hydra:next +
    64. 7.20 hydra:object +
    65. 7.21 hydra:offset +
    66. 7.22 hydra:operation +
    67. 7.23 hydra:pageIndex +
    68. 7.24 hydra:pageReference +
    69. 7.25 hydra:possibleStatus +
    70. 7.26 hydra:possibleValue +
    71. 7.27 hydra:previous +
    72. 7.28 hydra:property +
    73. 7.29 hydra:readable +
    74. 7.30 hydra:required +
    75. 7.31 hydra:resolveRelativeUsing +
    76. 7.32 hydra:returns +
    77. 7.33 hydra:returnsHeader +
    78. 7.34 hydra:search +
    79. 7.35 hydra:statusCode +
    80. 7.36 hydra:subject +
    81. 7.37 hydra:supportedClass +
    82. 7.38 hydra:supportedOperation +
    83. 7.39 hydra:supportedProperty +
    84. 7.40 hydra:template +
    85. 7.41 hydra:title +
    86. 7.42 hydra:totalItems +
    87. 7.43 hydra:variable +
    88. 7.44 hydra:variableRepresentation +
    89. 7.45 hydra:view +
    90. 7.46 hydra:writable
  • 8 Named instances
      -
    1. 8.1 hydra:BasicRepresentation -
    2. 8.2 hydra:ExplicitRepresentation -
    3. 8.3 hydra:LinkContext -
    4. 8.4 hydra:Rfc3986 +
    5. 8.1 hydra:Available +
    6. 8.2 hydra:BasicRepresentation +
    7. 8.3 hydra:ExplicitRepresentation +
    8. 8.4 hydra:LinkContext +
    9. 8.5 hydra:Rfc3986 +
    10. 8.6 hydra:Unauthorized +
    11. 8.7 hydra:Unavailable
  • 9 Data types @@ -2662,6 +2667,45 @@

    Direct usage of supportedOperation on rdf:Property without elevating it to the Link SHOULD NOT be implemented as clients may not discover such a construct correctly.

    +

    There are rare situations when some supported operations once announced in the +API documentation should be retracted, i.e. to reflect current state of the +application or current user capabilities (or lack of them). It is doable +with the availability predicate that can be added to the Operation itself. By default all operations are Available without limits and it +is up for the server to change that, and for the client to discover any +discrepancies compared against the API documentation in the runtime. Yet +server may want to inform the client that at the very moment an operation is either Unavailable or Unauthorized. The latter MAY be used to notify +client that the user used to invoke the request that provides operation +availability information is currently not authorized for that very operation +to be invoked. The former on the other hand MAY be used to inform that +the operation is currently unavailable and client SHOULD NOT invoke it. +Server MAY also provide more custom reasons for which the operation is not +available but it SHOULD provide at least one of the _Hydra_ built in reasons.

    +

    Usage of the availability is restricted only to the Operations +and MUST NOT be used on SupportedOperations. The availability predicate also MUST take precedence over a supported operation declaration. +The operation that comes with availability predicate SHOULD be identified +using any of the below enlisted methods:

    + +
    + +
    EXAMPLE: Retracting operations - declaration of supported operations
    +
    {  "@context": "http://www.w3.org/ns/hydra/context.jsonld",  "@id": "http://api.example.com/doc/#comments",  "@type": "Link",  "supportedOperation": [    {      "@type": "Operation",      "method": "POST",      "expects": "http://api.example.com/doc/#Upload"    },    {      "@type": "Operation",      "method": "POST",      "expects": "http://api.example.com/doc/#Comment"    }  ]}
    +
    +
    + +
    EXAMPLE: Retracting operations - matching
    +
    {  "@context": "http://www.w3.org/ns/hydra/context.jsonld",  "@id": "http://api.example.com/doc/",  "@type": "Collection",  "operation": [    {      "@type": "Operation",      "method": "POST",      "expects": "http://api.example.com/doc/#Upload",      "availability": "Unavailable"    }  ]}
    +
    +

    In the example above the operation that expects an uploaded file became Unavailable, while the one expecting a comment remains available as +the expects predicate does not match any supported operations. +It is still recommended to mark operations being subject for further +restrictions with an Iri as from the client perspective this may be +easier to implement simple literal Iri comparison rather than to compare +graphs of objects.

    Note: These are the simple example scenarios and possible usages are not limited to those described above.

    Due to the fact an ApiDocumentation as all other resources may fail @@ -2911,6 +2955,20 @@

  • IRI expansion should be performed with respect to the specification behind the IRI template type ([RFC6570] by default), and the product @@ -2930,7 +2988,7 @@