If you would like to see an example of a web application leveraging the RERUM API visit the official RERUM Sandbox and public sandbox API https://tinydev.rerum.io. You can use the following RERUM Sandbox API links to give your application simple CRUD and query abilities.
Your data will be public and could be removed at any time. The sandbox functions as a public testbed and uses the development API; it is not meant for production applications.
Access Tokens are required in order to communicate with the RERUM API. These Access Tokens are for the application so that RERUM can verify which application is making an API request and attribute data properly. To register, one must visit the registration page at https://devstore.rerum.io/v1/. Registration requires an E-mail address and a name, which is typically a webmaster or principal investigator in charge of the application's wellbeing. The result of registration is a Refresh Token and an Access Token. Do not lose the Refresh Token as it is used by the application to get new valid Access Token throughout the application lifespan. To see how this process works, see the TinyThings application which has a token module that implements token refreshes. Registrants can get new Refresh Tokens from the RERUM registration page by logging in again. When a new token is provided old tokens are expired.
Note that the same Refresh Token and Access Token can be used for multiple applications. However, the data from each of those applications will share the same application generator
attribution and will not be considered separate applications.
Create, Update, and Delete requests require valid Access Tokens or else the API will return Unauthorized errors. To provide an Access Token, application HTTP requests use the Authorization
header to provide a 'Bearer Token'. It has the format 'Beaer: Access Token' as seen below.
"Authorization": "Bearer eyJz93a...k4laUWw"
You will see many examples in this document that use this HTTP header.
For those who Copy and Paste please note that all examples are using the development (devstore.rerum.io) version of the RERUM API, not the production version (store.rerum.io). Only use production once you have become confident with the API and have confirmed your application is generating data as expected.
Patterns | Payloads | Responses |
---|---|---|
/id/_id |
empty |
200 {JSON} |
_id
—the id of the record in
RERUM.{JSON}
—The record
with identifier _id
const entity = await fetch("https://devstore.rerum.io/v1/id/11111").then(resp => resp.json()).catch(err => {throw err})
This can be used directly in the browser. Try it to see what the response resp
looks like.
https://devstore.rerum.io/v1/id/11111
Patterns | Payloads | Responses |
---|---|---|
/history/_id |
empty |
200 [{JSON}] |
_id
—the id of the record in
RERUM.[{JSON}]
—an array
of the resolved records of all parent history recordsAs records in RERUM are altered, the previous state is retained in a history tree. Requests return ancestors of this record on its branch. The records in the array are listed in inorder traversal but ignoring other branches.
const history_array = await fetch("https://devstore.rerum.io/v1/history/11111").then(resp => resp.json()).catch(err => {throw err})
This can be used directly in the browser. Try it to see what the response resp
looks like.
https://devstore.rerum.io/v1/history/11111
Patterns | Payloads | Responses |
---|---|---|
/since/_id |
empty |
200 [{JSON}] |
_id
—the id of the record in
RERUM.[{JSON}]
—an array
of the resolved records of all child history records
As records in RERUM are altered, the next state is retained in
a history tree. Requests return all descendants of this record from all branches.
The records in the array are listed in preorder traversal.
const since_array = await fetch("https://devstore.rerum.io/v1/since/11111").then(resp => resp.json()).catch(err => {throw err})
This can be used directly in the browser. Try it to see what the response resp
looks like.
https://devstore.rerum.io/v1/since/11111
Patterns | Payloads | Responses |
---|---|---|
/client/request-new-access-token |
{JSON} |
200 {JSON} |
{JSON}
— Auth0 requirements here{JSON}
— Containing
the Auth0 /oauth/token JSON
responseRERUM works as a proxy with Auth0 to help manage tokens from registered applications.
const access_token = await fetch("https://devstore.rerum.io/client/request-new-access-token", {
method: "POST",
headers:{
"Content-Type": "application/json; charset=utf-8"
},
body: JSON.stringify({
"refresh_token": "faJw88b...l4leYIw"
})
})
.then(resp => resp.json())
.then(info => info.access_token)
.catch(err => {throw err})
resp
looks like
{
"access_token": "eyJz93a...k4laUWw",
"refresh_token": "GEbRxBN...edjnXbL",
"id_token": "eyJ0XAi...4faeEoQ",
"token_type": "Bearer",
"expires_in": 86400
}
Application managers must use the RERUM Registration Page to get new Refresh Tokens. Applications are not able to ask for new Refresh Tokens like they can ask for new Access Tokens.
Patterns | Payloads | Responses |
---|---|---|
/create |
{JSON} |
201 Location: https://devstore.rerum.io/v1/id/abcdef1234567890
{JSON} |
{JSON}
—The object to create
{JSON}
—Containing
various bits of information about the create.
Add a completely new object to RERUM and receive the Location
URI
as a response header and the complete RERUM record as the response body. Accepts only single JSON objects in the request body.
The __rerum
, @id
and _id
properties are ignored.
const saved_obj = await fetch("https://devstore.rerum.io/v1/api/create", {
method: "POST",
headers:{
"Authorization": "Bearer eyJz93a...k4laUWw"
"Content-Type": "application/json; charset=utf-8"
},
body: JSON.stringify({
"hello": "world"
})
})
.then(resp => resp.json())
.catch(err => {throw err})
resp
looks like:
{
"@id": "https://devstore.rerum.io/v1/id/abcdef1234567890",
"hello": "world",
"__rerum":{...}
}
Note that resp.headers.get("location") will return "https://devstore.rerum.io/v1/id/abcdef1234567890"
Patterns | Payloads | Responses |
---|---|---|
/bulkCreate |
[{JSON}] |
201
|
[{JSON}]
—an array of objects
to create in RERUM[{JSON}]
—an array
of the resolved records from the creation processAdd multiple completely new objects to RERUM and receive an array of the complete records as the response body. Accepts only a single array of JSON objects in the request body. The array of JSON objects passed in will be created in the order submitted and the response will have the URI of the new resource or an error message as an array in the same order. When errors are encountered, the batch process will attempt to continue for all submitted items.
const saved_obj = await fetch("https://devstore.rerum.io/v1/api/bulkCreate", {
method: "POST",
headers:{
"Authorization": "Bearer eyJz93a...k4laUWw"
"Content-Type": "application/json; charset=utf-8"
},
body: JSON.stringify([
{"hello": "sun"},
{"goodbye": "moon"}
])
})
.then(resp => resp.json())
.catch(err => {throw err})
resp
looks like:
[
{
"@id": "https://devstore.rerum.io/v1/id/abcdef1234567890",
"hello": "sun",
"__rerum":{...}
},
{
"@id": "https://devstore.rerum.io/v1/id/1234567890abcdef",
"goodbye": "moon",
"__rerum":{...}
}
]
Patterns | Payloads | Responses |
---|---|---|
/query?limit=10&skip=0 |
{JSON} |
200 [{JSON}] |
{JSON}
—the properties in JSON
format for the query[{JSON}]
—an array
of the resolved records that match the query
This simple format will be made more complex in the future, but should serve the basic needs as it is.
RERUM will test for property matches. By default, this is limited to 10 records in the response to guard against unreasonable queries. To allow for more records in the response one can add the URL parameter limit
to the query requests. If you expect the query request will have a very large response with many objects, your application should use a paged query by also using the skip
URL parameter. You will see an example of this below.
Note that your application may experience strange behavior with large limits, such as ?limit=1000. It is recommended to use a limit of 100 or less. If you expect there are more than 100 matching records, use a paged query to make consecutive requests until all records all gathered.
const matched_objects = await fetch("https://devstore.rerum.io/v1/api/query", {
method: "POST",
headers:{
"Content-Type": "application/json; charset=utf-8"
},
body: JSON.stringify(
{"type": "Object", "shape": "round"}
)
})
.then(resp => resp.json())
.catch(err => {throw err})
resp
looks like:
[
{
"@id": "https://devstore.rerum.io/v1/id/abcdef1234567890",
"type": "Object",
"shape": "round",
"name": "Ball",
"__rerum":{...}
},
{
"@id": "https://devstore.rerum.io/v1/id/1234567890abcdef",
"type": "Object",
"shape": "round",
"name": "Globe",
"__rerum":{...}
},
...
]
All responses are a JSON Array that is not ordered, even if a single or zero records are matched.
const many_results = await pagedQuery(100, 0, {"type": "Thing"})
function pagedQuery(lim, it = 0, queryObj, allResults = []) {
return fetch(`https://devstore.rerum.io/v1/api/query?limit=${lim}&skip=${it}`, {
method: "POST",
headers: {
"Content-Type": "application/json; charset=utf-8"
},
body: JSON.stringify(queryObj)
})
.then(response => response.json())
.then(results => {
if (results.length) {
allResults = allResults.concat(results)
return pagedQuery(lim, it + results.length, queryObj, allResults)
}
return allResults
})
.catch(err => {
console.warn("Could not process a result in paged query")
throw err
})
}
This section is non-normative.
Some programming languages and some servers do not consider PATCH
to be a standard method.
As a result, some software is unable to make a PATCH
update request directly.
RERUM still wants these applications to fit within these standards. We support
the X-HTTP-Method-Override
header on POST
requests to make them act like PATCH
requests
in this API.
Patterns | Payloads | Responses |
---|---|---|
/patch |
{JSON} |
200 Location: https://devstore.rerum.io/v1/id/1234567890abcdef
{JSON} |
{JSON}
—The record to patch
update.{JSON}
—Containing
various bits of information about the patch.Example Method Override Request:
const patched_obj = await fetch("https://devstore.rerum.io/v1/api/patch", {
method: "POST",
headers:{
"X-HTTP-Method-Override": "PATCH",
"Authorization": "Bearer eyJz93a...k4laUWw",
"Content-Type": "application/json; charset=utf-8"
},
body: JSON.stringify(
{
"@id": "https://devstore.rerum.io/v1/id/abcdef1234567890",
"existing_property": "new_value"
}
)
})
.then(resp => resp.json())
.catch(err => {throw err})
See the Patch Update section for details on the response resp
.
The __rerum
, @id
and _id
properties are ignored on all PUT requests.
Updates to released or deleted records fail with an error.
Replace an existing record through reference to its internal RERUM id and receive the Location
URI for the resulting record as a response header and the complete record as the response body.
This will have the effects of update, set, and unset actions.
New keys will be created and keys not present in the request will not be present in the resulting record.
When an object is updated, the @id
will change.
This results in the need to track history and the previous version will be represented in the __rerum.history.previous
of the resulting record.
Patterns | Payloads | Responses |
---|---|---|
/update |
{JSON} |
200 Location: https://devstore.rerum.io/v1/id/1234567890abcdef
{JSON} |
{JSON}
—The requested new
state for the record.{JSON}
—Containing various bits of
information about the PUT update.
const updated = await fetch("https://devstore.rerum.io/v1/api/update", {
method: "PUT",
headers:{
"Authorization": "Bearer eyJz93a...k4laUWw",
"Content-Type": "application/json; charset=utf-8"
},
body: JSON.stringify(
{
"@id": "https://devstore.rerum.io/v1/id/abcdef1234567890",
"be": "kind"
}
)
})
.then(resp => resp.json())
.catch(err => {throw err})
resp
looks like:
{
"@id": "https://devstore.rerum.io/v1/id/1234567890abcdef",
"be": "kind",
"__rerum":{
...
"history":{
"next": [],
"previous": "https://devstore.rerum.io/v1/id/abcdef1234567890",
"prime": "https://devstore.rerum.io/v1/id/abcdef1234567890"
}
}
}
Note that resp.headers.get("location") will return "https://devstore.rerum.io/v1/id/1234567890abcdef"
Note that the original record "https://devstore.rerum.io/v1/id/abcdef1234567890" now has
__rerum.history.next : ["https://devstore.rerum.io/v1/id/1234567890abcdef"]
RERUM allows the Generator of a record to overwrite that record. An error will be returned if the agent encoded in the request "Authorization" access token does not match the agent of the existing record.
Replace a record using a reference to its internal RERUM id and receive the
Location
URI for the resulting record as a response header and the complete record as the response body.
This will have the effects of update, set, and unset actions. New keys will be created and keys not present in the request will not be present in the resulting record.
The record is replaced in place, or overwritten, and so the @id
will not change and the history connected with this record will not be altered. The __rerum.isOverwritten
property will be set to the date and time of the overwrite.
Patterns | Payloads | Responses |
---|---|---|
/overwrite |
{JSON} |
200 Location: https://devstore.rerum.io/v1/id/abcdef1234567890
{JSON} |
{JSON}
—The requested new
state for the record.{JSON}
—Containing various bits of
information about the PUT overwrite.
const overwritten = await fetch("https://devstore.rerum.io/v1/api/overwrite", {
method: "PUT",
headers:{
"Authorization": "Bearer eyJz93a...k4laUWw",
"Content-Type": "application/json; charset=utf-8"
},
body: JSON.stringify(
{
"@id": "https://devstore.rerum.io/v1/id/abcdef1234567890",
"be": "kind"
}
)
})
.then(resp => resp.json())
.catch(err => {throw err})
resp
looks like:
{
"@id": "https://devstore.rerum.io/v1/id/abcdef1234567890",
"be": "kind",
"__rerum":{
...
"isOverwritten": "2023-07-19T19:06:24.030"
}
}
Note that resp.headers.get("location") will return "https://devstore.rerum.io/v1/id/abcdef1234567890"
Note that the @id
and __rerum.history
properties of the original record "https://devstore.rerum.io/v1/id/abcdef1234567890" have not changed. This is the difference between /update and /overwrite. Be careful.
The __rerum
, @id
and _id
properties are ignored on all PATCH requests.
Updates to released or deleted records fail with an error.
Patterns | Payloads | Responses |
---|---|---|
/patch |
{JSON} |
200 Location: https://devstore.rerum.io/v1/id/1234567890abcdef
{JSON} |
{JSON}
—The requested new
state for the record. MUST contain an @id
{JSON}
—Containing various bits of
information about the PATCH update.
A single record is updated by altering the set or subset of existing properties on the targeted RERUM record.
This method only manipulates existing record properties. Unmatched properties are ignored and will not appear
on the resulting patched record.
If {"key":null}
is submitted,
the value for property "key" will be set to null
instead of removing the property.
This results in the need to track history and the previous version will be represented in the __rerum.history.previous
of the resulting record.
const patched_obj = await fetch("https://devstore.rerum.io/v1/api/patch", {
method: "PATCH",
headers:{
"Authorization": "Bearer eyJz93a...k4laUWw",
"Content-Type": "application/json; charset=utf-8"
},
body: JSON.stringify(
{
"@id": "https://devstore.rerum.io/v1/id/abcdef1234567890",
"existing_property": "new_value",
"unmatched_property": "will be ignored"
}
)
})
.then(resp => resp.json())
.catch(err => {throw err})
resp
looks like:
{
"@id": "https://devstore.rerum.io/v1/id/1234567890abcdef",
"existing_property": "new_value",
"__rerum":{
...
"history":{
"next": [],
"previous": "https://devstore.rerum.io/v1/id/abcdef1234567890",
"prime": "https://devstore.rerum.io/v1/id/abcdef1234567890"
}
}
}
Note that resp.headers.get("location") will return "https://devstore.rerum.io/v1/id/1234567890abcdef"
Note that the original record "https://devstore.rerum.io/v1/id/abcdef1234567890" now has
__rerum.history.next : ["https://devstore.rerum.io/v1/id/1234567890abcdef"]
Patterns | Payloads | Responses |
---|---|---|
/set |
{JSON} |
200 Location: https://devstore.rerum.io/v1/id/1234567890abcdef
{JSON} |
{JSON}
—The requested new
state for the record MUST contain an @id
{JSON}
—Containing
various bits of information about the PATCH update.
A single RERUM record is updated by adding all properties in the JSON payload. This method only adds new record properties.
If a property in the payload matches an existing property it will be ignored.
This results in the need to track history and the previous version will be represented in the __rerum.history.previous
of the resulting record.
const patched_obj = await fetch("https://devstore.rerum.io/v1/api/set", {
method: "PATCH",
headers:{
"Authorization": "Bearer eyJz93a...k4laUWw",
"Content-Type": "application/json; charset=utf-8"
},
body: JSON.stringify(
{
"@id": "https://devstore.rerum.io/v1/id/abcdef1234567890",
"existing_property": "This value will be ignored",
"unmatched_property": "Some Value",
}
)
})
.then(resp => resp.json())
.catch(err => {throw err})
resp
looks like:
{
"@id": "https://devstore.rerum.io/v1/id/1234567890abcdef",
"existing_property": "I exist!",
"unmatched_property": "Some value",
"__rerum":{
...
"history":{
"next": [],
"previous": "https://devstore.rerum.io/v1/id/abcdef1234567890",
"prime": "https://devstore.rerum.io/v1/id/abcdef1234567890"
}
}
}
Note that resp.headers.get("location") will return "https://devstore.rerum.io/v1/id/1234567890abcdef"
Note that the original record "https://devstore.rerum.io/v1/id/abcdef1234567890" now has
__rerum.history.next : ["https://devstore.rerum.io/v1/id/1234567890abcdef"]
Patterns | Payloads | Responses |
---|---|---|
/unset |
{JSON} |
200 Location: https://devstore.rerum.io/v1/id/1234567890abcdef
{JSON} |
{JSON}
—The requested new
state for the record. Must contain an @id
.
{JSON}
—Containing various
bits of information about the PATCH update.
A single RERUM record is updated by removing all properties in the JSON payload. This method only removed existing record properties.
If a property in the payload does not match an existing property it will be ignored. Properties in the payload to remove must have the value null
or they will be ignored.
This results in the need to track history and the previous version will be represented in the __rerum.history.previous
of the resulting record.
const patched_obj = await fetch("https://devstore.rerum.io/v1/api/set", {
method: "PATCH",
headers:{
"Authorization": "Bearer eyJz93a...k4laUWw",
"Content-Type": "application/json; charset=utf-8"
},
body: JSON.stringify(
{
"@id": "https://devstore.rerum.io/v1/id/abcdef1234567890",
"existing_property": null,
"unmatched_property": "This property will be ignored"
}
)
})
.then(resp => resp.json())
.catch(err => {throw err})
resp
looks like:
{
"@id": "https://devstore.rerum.io/v1/id/1234567890abcdef",
// "existing_property": "I exist!" has been removed
"hello": "world",
"__rerum":{
...
"history":{
"next": [],
"previous": "https://devstore.rerum.io/v1/id/abcdef1234567890",
"prime": "https://devstore.rerum.io/v1/id/abcdef1234567890"
}
}
}
Note that resp.headers.get("location") will return "https://devstore.rerum.io/v1/id/1234567890abcdef"
Note that the original record "https://devstore.rerum.io/v1/id/abcdef1234567890" now has
__rerum.history.next : ["https://devstore.rerum.io/v1/id/1234567890abcdef"]
Patterns | Payloads | Responses |
---|---|---|
/release |
{JSON} |
200 Location: https://devstore.rerum.io/v1/id/11111
{JSON} |
{JSON}
—The record. Must
contain @id
.
RERUM allows for the Generator of a version of a record to assign a released
state.
Records in released states are locked such that further changes are refused.
Calling any update or delete action on a released record will result in an error response.
The release action will alter the __rerum.isReleased
of the version identified
and alter __rerum.releases
properties throughout
the record's history without making a
new history state for the resulting record (the @id
does not change).
const releasedObj = await fetch("https://devstore.rerum.io/v1/api/release", {
method: "PATCH",
headers:{
"Authorization": "Bearer eyJz93a...k4laUWw",
"Content-Type": "application/json; charset=utf-8"
},
body: JSON.stringify({"@id": "https://devstore.rerum.io/v1/id/abcdef1234567890"})
})
.then(resp => resp.json())
.catch(err => {throw err})
resp
looks like:
{
"@id": "https://devstore.rerum.io/v1/id/abcdef1234567890",
...
"__rerum":{
...
"isReleased": "2023-07-19T19:06:24.030"
"releases":{
...
}
}
}
Note that resp.headers.get("location") will return "https://devstore.rerum.io/v1/id/abcdef1234567890"
RERUM allows the Generator of a record to delete that record. An error will be returned if the agent encoded in the request "Authorization" access token does not match the agent of the existing record.
RERUM DELETE does not remove anything from the server. Deleted records are only marked as deleted.
Records marked as deleted do not return in query results and may only be directly retrieved by
@id
.
Deleted records are removed from history trees. RERUM will do this automatically when a record is deleted. This cannot be undone.
Patterns | Payloads | Responses |
---|---|---|
/delete |
{JSON} |
204 |
{JSON}
—The record to delete.
Must contain @id
.
fetch("https://devstore.rerum.io/v1/api/delete", {
method: "DELETE",
headers:{
"Authorization": "Bearer eyJz93a...k4laUWw",
"Content-Type": "application/json; charset=utf-8"
},
body: JSON.stringify({"@id": "https://devstore.rerum.io/v1/id/abcdef1234567890"})
})
.catch(err => {throw err})
Note that the 204 "No Content" code was returned, so there is no response body.
A deleted record is easily recognized by __deleted
{
"@id": "https://devstore.rerum.io/v1/id/abcdef1234567890",
"__deleted":{
"object":{
"@id": "https://devstore.rerum.io/v1/id/abcdef1234567890",
"hello": "sun",
"goodbye": "moon",
"__rerum":{...}
},
"deletor": GENERATOR_AGENT,
"time": "2023-07-19T19:06:24.030"
}
}
The __deleted.object
contains a snapshot of this version of the record when it was deleted, including its place in the
history.
The __deleted.deletor
is
the URI of the agent that marked this record as deleted.
__rerum
Property ExplainedEach record carries a protected property named __rerum
containing a metadata
object about the version retrieved.
Property | Type | Description |
---|---|---|
@context | String | The RERUM context file http://store.rerum.io/v1/context.json. |
alpha | Boolean | An Internal flag for RERUM API version control. |
APIversion | String | Specific RERUM API release version for this data node, currently 1.0.0. |
history.prime | String | The URI of the record initializing this history. |
history.next | [String] | An array of URIs for the immediate derivatives of this version. A length > 1 indicates a branch. |
history.previous | String | The URI of the immediately previous version. |
generatedBy | String | Reference to the authenticated application which committed this version. |
createdAt | timestamp | Though the record may also assert this about itself, RERUM controls this value. |
isOverwritten | timestamp | Written when the overwrite endpoint is used. Exposes the date and time of the change. |
isReleased | timestamp | Written when the release endpoint is used. Exposes the date and time this node was released. |
releases.previous | String | URI of the most recent released version from which this version is derived. |
releases.next | [String] | Array of URIs for the first released
decendant in the downstream branches. |
releases.replaces | String | URI of the previous release this node is motivated to replace. This is only present on released
versions and will always match the value of releases.previous . |
In the future, this may be encoded as an annotation on the record, using existing vocabularies, but for now the applications accessing RERUM will need to interpret this data if it is relevant.
History is stored through pointers that create a B-Tree. All nodes in the B-tree know the root node, the previous node, and the next node(s).
You can ask for all descendants or all ancestors from any given node so long as you know the node’s @id
and the node has not been deleted. See history parents and history
children for more details about this process.
Deleted records are not present in any B-Tree, but do exist as separate nodes that can be requested by the URI directly. A snapshot of their position at the time of deletion persists in these deleted nodes.
RERUM associates a foaf:Agent
with each action
performed on an item in __rerum.generatedBy
which
is referred to as the “Generator”. An API key authenticated application requesting an overwrite, release, or
delete action can only do so if they are the Generator of the record the action is performed on. If an
unauthorized application attempts one of these actions a 401 Unauthorized
response is returned with an
explanation on how to branch versions instead.
Applications are strongly encouraged to record their own assertions within the records, as consuming
applications may reliably use a combination of the authoritative generatedBy
property and an intrinsic creator
to establish a reliable attribution.
RERUM creates an Agent
for each successful
registration. This Agent
is in JSON-LD format and
stored publicly. Authentication is managed by Auth0.
When RERUM creates an Agent
, Auth0 generates a
refresh token and an access token. Applications are responsible for providing their access tokens via a
Authorization
Header in their CRUD requests.
Records in RERUM should be JSON-LD, which means they should have a @context
provided when they are created. However,
ordinary JSON documents are allowed in the store. These JSON documents can be interpreted as JSON-LD by
referencing a JSON-LD context document in an HTTP Link Header. RERUM
provides this @context
in the Link
header and also provides a @context
for the __rerum
terms mentioned above.
http://store.rerum.io/v1/context.json
RERUM fully supports the IIIF Presentation API.
RERUM follows the W3C Annotation protocol. Learn more about Web Annotation.
The intention of the API is to follow RESTful practices. These practices drive what requests we accept and what responses we have to the various scenarios around those requests. What it means to be RESTful varies wildly, but our efforts follow the guidelines at https://www.restapitutorial.com/resources.html
RERUM follows REST, IIIF and Web Annotation standards to form its responses to users. For more information about why RERUM chose a certain HTTP status code see the graph below.
If you are confused as to what type of requests give what response, review the Web Annotation and RESTful standards.