REST API

This is a draft document and it is subject to change often and without notice.

=How the REST API works=


 * 1) User contacts URL, which is handled by eXist
 * 2) URL activates database's controller, which routes the URL to the correct XQuery
 * 3) XQuery responds, returning a message header, body, and HTTP status code
 * 4) Each data type has a schema and is validated through the schema.

The UI acts like a client is totally separated from the REST implementation. The UI will have to compose REST operations in order to do useful work.

=Data formats=

The API supports two types of pages, both served by HTTP:
 * List resources, in a simple XHTML format. These pages support GET and may support POST:
 * Previous, Next, First, and Last links for long lists
 * Links to alternate TEI format pages
 * start, max-results query parameters
 * A main body containing list structures
 * If the page supports POST, an input indicating it
 * Object resources that directly represent parts of JLPTEI files, in JLPTEI format. These support GET and may support PUT and DELETE.


 * When a resource supports TEI format, it will have a .xml extension. If it's in XHTML list format, it will not have an extension.

=HTTP methods=

Important Note: because of a missing feature in eXist, HTTP PUT and DELETE are not supported directly in the REST API. Instead, they are simulated by HTTP POST with a query string (the part of the URL after ?) including _method=PUT or _method=DELETE. When the feature is included in eXist, both the _method simulation technique and actual PUT and DELETE operations will work.

=Authentication=

The API will aim to support HTTP Basic and session-based (non-RESTful) authentication, to the extent that it is possible. As far as I can tell, HTTP Basic auth won't be able to authenticate with OpenID.

= Major questions =
 * How does one support OpenID RESTfully?*
 * What granularity should the REST API have? (eg, for profile access, should there be one entry point /user/foo that returns/changes foo's profile, or should POST to /usr/foo/passwordHint change foo's password hint?)

=Common information=

The APIs may have a base (like /code/api) or be served from a subdomain (api.jewishliturgy.org)

Status codes
200 OK. The data is in the body of the message. 201 Created (to POST). The Location header points to a URI representing the created resource. 202 Accepted (to POST, when an event is queued) 204 No content (to PUT/POST) - OK but nothing to return 400 Bad Request (malformed or error) 401 Authentication required 403 Forbidden 404 Not found 405 Method not allowed (must include Allow header in response) 409 Conflict

All unlisted methods must return 405 Method not allowed with an Allow header in the response indicating allowed methods.

Content types
The API generally accepts two Content-types:
 * text/plain The content you're sending is plain text
 * application/xml or text/xml The content is XML content, usually a JLPTEI fragment

It returns:
 * text/plain Simple return values that can be expressed as text
 * application/xml XML data, usually a JLPTEI fragment
 * application/xml+xhtml XHTML, usually a menu

/
(Implemented in trunk)


 * GET
 * List available top-level APIs
 * Status code: 200

/user
(Implemented)


 * GET
 * Purpose: List user functions
 * Return: XHTML list of user functions
 * Status codes: 200

/user/login
Session-based (non-REST) login


 * GET
 * Get current logged in user
 * Status codes: 200

/user/login/{NAME}
(Implemented)


 * PUT
 * Log in as the given user NAME with the password contained in the request
 * Status codes: 204 (user is valid and now logged in), 400 (user or password wrong)


 * DELETE
 * Log out the current user
 * Status codes: 204

/user/logout
(Implemented)


 * GET or POST
 * Log the current user out
 * Status codes: 204

/user/{NAME}
(Implemented)


 * GET
 * List user profile functions
 * Status code: 200 (user exists and is logged in), 204 (user exists, but is not authenticated), 403 (authenticated as the wrong user), 404 (user does not exist)


 * PUT
 * Create a new user/set password
 * Content: Password string
 * Status code: 200 (password set), 201 (user created), 403 (authenticated as the wrong user), 409 (user already exists)

/user/{NAME}/name
(Implemented)


 * GET
 * Get user name
 * Status code: 200, 401, 403


 * PUT
 * Set user name
 * Status code: 200, 401, 403

/user/{NAME}/orgname
(Implemented)


 * GET
 * Get organization name
 * Status code: 200, 401, 403


 * PUT
 * Set organization name
 * Status code: 200, 401, 403

/user/{NAME}/email
(Implemented)


 * GET
 * Get email address
 * Status code: 200, 401, 403


 * PUT
 * Set email address
 * Status code: 200, 401, 403

/user/{NAME}/groups

 * GET
 * Get group memberships
 * Status code: 200, 401, 403

(Note: to add a user to a group, POST the user to /group/{NAME}/members)

/group

 * GET
 * List available groups
 * Status codes: 200, 401, 403

/group/{NAME}

 * GET
 * List collections available under the group
 * Status codes: 200, 401, 403, 404


 * PUT
 * Make a new group
 * Status codes: 204 (already exists and you're a member), 201, 401, 403


 * DELETE
 * Remove a group
 * Status codes: 204, 401, 403, 404

/group/{NAME}/member

 * GET
 * List members of a group
 * Status codes: 200, 401, 403

/group/{NAME}/member/{UNAME}

 * GET
 * List if UNAME is a member of the group
 * Status codes: 200, 401, 403, 404


 * PUT
 * Add UNAME as a member of the group
 * Status codes: 200, 201, 403, 404


 * DELETE
 * Remove UNAME as a member of the group

/group/{NAME}/profile

 * GET
 * List profile resources
 * Status codes: 200, 401, 403

/group/{NAME}/administrator

 * GET
 * List administrators for the group
 * Status codes: 200, 401, 403

/group/{NAME}/administrator/{UNAME}

 * GET
 * List is {UNAME} is an administratorr of the group
 * Status codes: 200, 401, 403, 404


 * PUT
 * Set UNAME as an administrator of the group
 * Status codes: 200, 201, 403, 404


 * DELETE
 * Remove UNAME as an administrator of the group
 * Status codes: 204, 403, 404

/group/{NAME}/profile/permissions

 * GET
 * List possible profile permissions
 * Status codes: 200, 401, 403

/group/{NAME}/profile/permissions/read

 * GET
 * Non member read permissions
 * Status codes: 200, 401, 403


 * PUT
 * Set non-member read permissions
 * Status codes: 200, 201, 401, 403


 * DELETE
 * Remove non-member read permissions
 * Status codes: 204, 401, 403

===/group/{NAME}/members/{MNAME}


 * GET
 * Get member's status in a group
 * Status codes: 200 (MNAME is a member), 401, 403, 404 (MNAME is not a member)


 * PUT
 * Add a member to the group
 * Status codes: 200 (MNAME is already member), 201 (MNAME has been added), 401, 403, 404 (MNAME is not a user)


 * DELETE
 * Remove a member from a group (may only be done by group admins)
 * Status codes: 204, 401, 403

/data
(Implemented)


 * GET
 * Return a list of possible data types
 * Status codes: 200

/data/original
(Implemented)


 * GET
 * Return a list of available original text resources
 * Status: 200 + menu (menu of available functions), 401 (you are not logged in and requested a resource that requires login), 403 (you are logged in, but you can't access the resource), 404 share type, group or user does not exist

/data/original/group
(Implemented)


 * GET
 * Return a list of available original text resources within all accessible groups
 * Status: 200 + menu (menu of available functions), 401 (you are not logged in and requested a resource that requires login), 403 (you are logged in, but you can't access the resource), 404 share type, group or user does not exist

/data/original/group/{OWNER}
(Implemented)


 * GET
 * Return a list of available original text resources with the given group OWNER
 * Status: 200 + menu (menu of available functions), 401 (you are not logged in and requested a resource that requires login), 403 (you are logged in, but you can't access the resource), 404 share type, group or user does not exist


 * POST
 * Return the location of a newly templated JLPTEI resource that has the given OWNER
 * Status: 201 (Resource created, location header set), 401 (Access to the resource requires authorization), 403 (You are logged in, but you can't access the resource), 404 (Share-type, user or group does not exist)

/data/original/group/{OWNER}/{RESOURCE}

 * GET
 * List resources or collections under the collection
 * Status codes: 200, 401, 403, 404


 * POST
 * Post a new empty resource under the collection
 * Return: Location header contains resource URI
 * Status codes: 201, 401, 403


 * DELETE
 * Delete a custom collection (reserved collections are immune to deletion)
 * Status codes: 204, 400

{OWNER}/{COLLECTION}/{RESOURCE}

 * GET
 * Retrieve a list of sub-resources and representations of the resource
 * Status codes: 200, 401, 403, 404


 * PUT (?)
 * Add or replace the resource with a complete, valid one
 * Status codes: 200, 201, 400, 401, 403


 * DELETE
 * Remove the resource


 * Status codes: 204, 401, 403

Contributor resources

 * GET
 * Retrieve a list of contributors
 * Status codes: 200, 401, 403


 * POST
 * Add a new contributor
 * Status codes: 201, 401, 403

contributor/{ID}

 * GET
 * Retrieve a list of contributor properties
 * Status codes: 200, 401, 403


 * DELETE
 * Remove the contributor (no references to it!)
 * Status codes: 204, 400

contributor/{ID}/name

 * GET
 * Get name
 * Status codes: 200, 401, 403


 * PUT
 * Set name
 * Status codes: 200, 201, 401, 403

contributor/{ID}/orgname

 * GET
 * Organizational contributor name
 * Status codes: 200, 401, 403


 * PUT
 * Set name
 * Status codes: 200, 201, 401, 403

Basic data resources
{RESOURCE}/{SUBRESOURCE} is a stand-in for the full path to the resource


 * GET
 * Get subresource content
 * Status codes: 200, 401, 403, 404


 * PUT
 * Set subresource content
 * Status codes: 200, 201, 400 (bad content), 401, 403, 404


 * POST
 * Add a subresource child
 * Status codes: 201, 400, 401, 403


 * DELETE
 * Remove subresource
 * Status codes: 204, 400 (if delete is inapplicable), 401, 403

lang
Resource language
 * Methods: GET, PUT
 * Content-type: text/plain
 * Supported by: most resources

title
Resource title
 * Methods: GET, PUT
 * Content-type: application/xml
 * Supported by: main resource
 * Sub-resources: lang

subtitle
Resource subtitle
 * Methods: GET, PUT, DELETE
 * Content-type: application/xml
 * Supported by: main resource
 * Sub-resources: lang

license
License
 * Methods: GET, PUT
 * Content-type: text/plain
 * Content: URI that points to a supported license
 * Supported by: main resource

source
Pointer to the source(s) that the given resource draws from
 * Methods: GET, POST
 * Supported by: most resources

condition
Pointer to all conditions that affect the given resource
 * Methods: GET, POST
 * Supported by: textual resources

repository
Unordered set of textual segments contained within the resource


 * Methods: GET, POST
 * Content-type: application/xml (text/html?)
 * Content: List of contained segments

repository/{ID}
A single segment in a repository


 * Methods: GET
 * Content-type: application/xml
 * Content: tei:seg
 * Subresources: lang, w

selection
Content ordering of repository
 * Methods: GET, POST
 * Content-type: application/xml (text/html?)
 * Content:ordered list of repository entries

selection/{ID}

 * Methods: GET, PUT, DELETE
 * Content-type: application/xml (tei:ptr)
 * Subresources: targetresource, targetid, before, after

selection/{ID}/before|after
Represent the resources immediately before or after {ID} in the selection.


 * Methods: GET, POST, PUT, DELETE
 * Subresources: same as {ID}

POST adds a new resource before|after {ID}, just like POST to selection, except with a position, PUT moves a resource that already exists into the given position. Changing a resource's position in the selection will also change its position in all views that reference it.

view
Ways of dividing the selection into multiple hierarchies:


 * Methods: GET, POST

Get returns all views

view/{ID}

 * Methods: GET, POST, DELETE

Search API
Those resources that support the search API will support the following query parameters, using the HTTP GET method:
 * q: query, Initiates the search API
 * start: start result number, where the first result and default is 1.
 * max-results: maximum number of results to return, default is 50.