Joomla CMS Web Services API Specification
Joomla CMS Web Services API Specification
Abstract
This document describes version 1 of a standard API for web services for the Joomla
Content Management System using the [REST] architectural style. This is a working
document of the Web Services Working Group [WSWG] of the Joomla project and is part of
an initiative led by the Joomla Production Leadership Team.
The standard attempts to be a pragmatic one rather than a strictly RESTful one. It specifies
a standard URI structure and semantics, standard request message and standard response
message formats. Although most of the examples are in [JSON] and JSON is the
recommended format and the most likely to be implemented first, it is easy to envisage other
formats, such as XML being supported too.
The proposed standard is designed to be easily extended by third-party developers and fully
supports multi-lingual web services.
This document does not attempt to describe how the API might be implemented in any
particular version of Joomla. Indeed, it could be implemented in completely different ways in
different versions.
Notes to Readers
Comments, corrections and amendments to this document are invited and welcomed on the
Joomla CMS Development mailing list [JCMS].
Where syntax is to be defined this specification makes use of the Augmented Backus-Naur
Form (ABNF) [RFC5234] notation.
Text surrounded by square brackets indicates a reference. A list of references can be found
at the end of this document.
Requirements
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”,
“SHOULD NOT”, “RECOMMENDED”, “MAY” and “OPTIONAL” in this document are to be
interpreted as described in [RFC2119].
Copyright Notice
Copyright © 2013 Open Source Matters, Inc. and the persons identified as the document
authors. This document is distributed under the terms of the Joomla Electronic
Documentation License [JEDL].
Table of Contents
Page 1
Joomla CMS Web Services API Specification
Abstract
Notes to Readers
Requirements
Copyright Notice
Table of Contents
Introduction
Hypermedia as the engine of application state
Media types
URI terminology
Basic resource access
Entry point
Content negotiation
Media type negotiation
Language negotiation
Representation formats
JSON and JSON-P
XML
Requesting a resource
Conditional requests
Creating a new resource
Updating a resource
Deleting a resource
Filtering requests
Comparison operators
Linked resources
One-to-many relationships
Many-to-many relationships
Partial responses
Search
Basic search
Smart Search
Authentication
Error handling
Cross-domain Ajax using JSON-P
Alternative for clients that only support GET
Implementation Notes
Appendix: Reserved query arguments
References
Author contact details
Document History
Introduction
The primary purpose of a web services API is to expose data and the functionality
associated with that data as a collection of discrete services in such a way that client code
does not need to know or care about how each service is implemented. Changes to a
service implementation due to, say, architectural changes in the platform or the CMS, should
Page 2
not affect client code because of the isolation provided by the API. For this reason it is
expected that API versions will be more long-lived than the CMS releases that support them.
In general this document does not specify how a web service API is to be implemented and
it may be implemented in different ways in different versions of the CMS or indeed in
different components or standalone applications.
It is expected that third-party developers will want to add additional resources to the list of
those available from the core CMS. This specification should be considered open-ended and
subject to further extension by third-party developers.
The intention is to keep the API as simple as possible for both client and server developers
to use, but at the same time providing sufficient power and flexibility so as not to unduly
restrict what is possible. The API should also be easy for developers to understand without
needing to refer to documentation. Using the REST methodology and striving for semantic
naming and consistency of implementation all make the learning curve easier to climb. It is
also intended that the API should be scalable so that it remains viable on large and
distributed sites.
However, it should be noted that strict adherence to the hypermedia tenet can result in
delays associated with request-response round trips that can be avoided by relaxing the
requirement that clients should treat link URLs as being opaque. Often a client can be made
to retrieve exactly the information it needs with a single request if it is allowed to craft the
URL using out-of-band knowledge of URL structure. But in doing so it must be recognised
that any changes to server URLs may break the client and therefore the client is responsible
for the consequences of not treating URLs as being opaque.
This specification therefore has two audiences that are different but related. Developers of
server-side web services need to be concerned with URL structure and the semantics of
request arguments. On the other hand, client-side developers should only be concerned
with understanding link relation semantics and the use of the different media types.
Media types
The design of the API around hypermedia revolves around media type and link relation
definitions. Each of the media types used by the Joomla CMS web API is specified in a
separate document, but each is derived from a set of common features defined in the base
media type. The following media types are considered part of this specification but are
defined in separate documents:
Page 3
Media type Comments
URI terminology
This document refers to the various parts of a URI using the following standard terminology
defined in [RFC3986].
URI = scheme "://" authority "/" path [ "?" query ] [ "#" fragment ]
Note that a trailing slash SHOULD NOT be added at the end of the path segment of the URI
and the service MUST return a 301 Moved permanently to the equivalent URI without the
trailing slash in such cases.
The path part of the URI for an API call consists of an entry point, followed by a structured
path to a specific resource that is available from the API. Note that the forward slash always
indicates a hierarchical relationship of the individual path segments.
For clarity the entry point is usually omitted from the URIs shown in this specification.
The query part of the URI will typically consist of an ampersand-separated list of query
variables and their values. The order in which these key-value pairs occur is not significant
and the service MUST NOT depend on any particular ordering.
The fragment is not used in this specification and so fragment semantics are undefined in
this context.
http://www.domain.com/api/v1/articles?page=3&perPage=20
where
scheme = “http”
authority = “www.domain.com”
path = “api/v1/articles”
entry-point = “api/v1”
Page 4
resourcepath = “articles”
query = “page=3&perPage=20”
fragment = “”
GET /articles
GET /articles/37476
The first refers to all articles, whereas the second refers to a single article specified by the id
number given. The first will always return a list of articles, even though that list may contain
only one or zero individual articles. Note that both forms use the exact same name for the
resource even though the first returns exactly one article while the second will return an
arbitrary number of articles. The resource will always be referred to by that name throughout
the API.
The following is a summary of the REST semantics used by the API for the basic create,
read, update and delete (CRUD) operations. Note that the entry point and other aspects of
the HTTP protocol have been omitted from these examples.
If the resource name is not recognised then the service MUST return a 404 Not found status.
Note that resource names MAY be namespaced as described later in this document.
Page 5
Important: This specification talks a lot about the structure and intended semantics of the
URLs required to interact with web services. However, it is important to understand that
client software should regard URLs as opaque and SHOULD NOT parse them or try to infer
any semantics from their structure. The structure guidelines given here are for the benefit of
server software developers who will be exposing resources to client software via web
services. Where URI templates are used client software SHOULD NOT do anything beyond
blindly performing the necessary token substitutions.
Entry point
In order to promote discoverability of the API a GET call to the entry point URL will return
meta information about the API, contained in a service document. The response MUST be
an object with media type application/vnd.joomla.service.v1. Depending on the outcome of
content negotiation, there may be a specific format added to this base type. For example, a
JSON response will have media type application/vnd.joomla.service.v1+json.
This resource is read-only so attempts to use POST, PUT or DELETE will result in a 400
Bad request error from the server.
Implementations MUST NOT rely on parsing the entry point URL to convey any useful
information. For example, a server might choose the following as the entry point for a
collection of web services:
http://www.domain.com/api/v1/en-GB/json/
However, neither the server itself, nor any clients accessing web services through that URL,
should necessarily infer from this that the service provided is using version 1 of the API, or
that it is in English or uses JSON format.
This does not mean that the version, language or format should not appear anywhere in the
URL of a web service. As arguments in the query part of a request they are certainly valid
parts of the negotiation process as described below. Furthermore, it may be convenient for
an implementation to separate the codebase for different versions of the API by installing
them in distinct sub-directories, labelled by version number. However, any particular version
of the API should function identically regardless of whether the entry point includes a version
number or not.
GET / http://api.domain.com/
succe
ss
200 OKContent-Type:
application/vnd.joomla.service.v1
Note that access control rules apply, so the information returned may be different depending
on the access level of the client making the call. See later in this document for details on
how to authenticate a request.
Page 6
Content negotiation
In order for unambiguous communication between client and server to be established,
various aspects of the messages that they will exchange must be negotiated. Most notably,
these include, but are not restricted to, API version and representation format. These are
referred to in this document as "negotiated properties".
In all cases where negotiation is required client requests SHOULD include the correct HTTP
header fields for the negotiated properties. However, there are cases where clients cannot
generate a particular HTTP header field, or cannot provide the correct HTTP header field for
a negotiated property. In such cases, the client MAY include a parameter in the query part
of the request with the same name as the HTTP header field. Servers MUST use the value
given in the query part in preference to that given in the HTTP header field.
In all cases where negotiation is required server responses MUST include the correct HTTP
header fields for the negotiated properties. The server response message body MUST
include top-level properties for all negotiated properties. The values MUST exactly match
those given in the HTTP headers. This is so that clients that cannot reliably read HTTP
header fields will still be able to access the negotiated property values.
Accept
Content-Type
Content-Language
Servers are under no obligation to support the overriding of any HTTP header fields not
listed in this document as being negotiated properties.
Clients and servers are encouraged to use the Joomla vendor-specific media types based
on application/vnd.joomla.base.v1 and described in detail in [base], [service], [list] and [item].
The last part of the base media type is the version number of the API. It SHOULD NOT
represent the version of the Joomla CMS or the Joomla Platform. Ideally the version
number SHOULD consist of a major number only. Addition of a minor version number is
discouraged. When comparing version numbers, the server MUST use the PHP
version_compare function or a functionally equivalent algorithm.
In order to ensure that responses are correctly cached, servers MUST include this header in
their responses:
Page 7
Vary: Content-Type
This indicates that responses that have the same URL but differ in their Content-Types are
not the same and must be cached separately. It is not necessary to include Vary as a top-
level property in the response message body.
The media type MAY include an optional schema parameter that specifies the resource
schema for requests where the expected response is a single resource item (and not a
collection response that happens to contain just a single item) This can be further extended
by including an optional version number as part of the schema, separated by a dot and
beginning the lowercase letter “v”. For example,
application/vnd.joomla.{type}.v1+json; schema=articles.v2
specifies that version 2 of the articles schema is to be used within the context of version 1 of
the API. This allows schemas to change independently of the API. Ideally, the version
number SHOULD consist of a major version number only. Addition of a minor version
number is discouraged. When comparing version numbers, the server MUST use the PHP
version_compare function or a functionally equivalent algorithm.
Clients MAY omit the version number in the schema. If they do so then the server SHOULD
attempt to use the latest version of the schema that it supports and MUST include the
version number in the schema name that it returns.
In the event that the schema parameter value in the Accept header differs from the resource
name specified by the request itself then the schema parameter value SHOULD be ignored.
However, if a schema parameter value in an accept query argument differs from the
resource name specified by the request itself, then the server SHOULD respond with 415
Media type not recognised.
Clients that are unable to manipulate the Accept header in their requests, MAY add an
accept argument to the query part of the request URL. For example,
GET /articles/1234?accept=application/vnd.joomla.item.v1;schema=articles.v2
GET /articles/1234
Accept: application/vnd.joomla.item.v1; schema=v2
The format of the accept query argument is the same as the Accept header field as defined
in [RFC2616]. This includes the possibility of specifying multiple comma-separated media
types and providing relative quality parameters. Note that as a query argument it MUST be
url-encoded. The use of the accept query argument should be considered a last resort.
Clients SHOULD use the Accept header field if at all possible.
If a client requests a media type that the server does not support then the server SHOULD
respond with a "415 Media type not supported" status code. The server SHOULD also
Page 8
return a message body containing an error message and including a description of why the
error occurred. For example,
{
“describedby”: “http://docs.joomla.org/API_errors/v1/Media_type_not_recognised”,
"title": “Media type must be application/vnd.joomla.item.v1+json.”,
“requested”: “application/xml”
}
If the client does not specify a version number in the request then the server SHOULD
respond with the latest version that it is capable of delivering. This applies to both API
versions and schema versions.
If the client specifies more than one format in the Accept header then the normal rules of
precedence as described in [RFC2616] apply.
Servers SHOULD support the format query argument as a convenient shorthand way to
override the Accept header in requests. Acceptable values for the format argument are the
generic format names. For example, format=json is equivalent to accept=application/json
and indicates that the server SHOULD respond with the latest version of the API and the
latest schema version where applicable. If a format argument and an accept argument are
both present, the format argument SHOULD be ignored.
In the following table of examples, the server supports API version 3 and version 5 of the
articles schema, but no other versions.
Request Response
Page 9
media types.
Language negotiation
Clients SHOULD include an Accept-Language header to convey language preferences to
the server. Servers MAY use this header to determine the language of any status or error
messages returned by the API.
However, content language negotiation SHOULD NOT affect the resources sent or returned
via the API. This is because Joomla regards two content items containing the same content
but in different languages as being different resource items. For example, if an article is
available in both English and French versions, then they MUST have different unique ids and
hence different unique URLs. It MUST NOT happen that a request for the same resource
item URL will yield a different resource item depending on the Accept-Language header.
The server MAY include link objects within the response body to the equivalent resource
item in different languages if it can be determined that the items are equivalent. In such
cases the hreflang property of the link object MUST be set to the language code that the
server will respond with if the link is followed.
Servers SHOULD include a Content-Language header to indicate which language has been
selected. For example,
Content-Language: da
If more than one language is available on a server such that status or error messages may
differ depending on the Content-Language chosen, then the server MUST include the
following header in all responses:
Vary: Content-Language
Page 10
URI's are for machine use rather than human use and so it is not considered necessary to
translate the URI segments, although a third party extension developer may choose to name
a resource provided by their extension with a localised name.
Representation formats
This specification is largely agnostic regarding representation formats although most of the
examples are in JSON and JSON is the recommended format and the most likely to be
implemented first in the Joomla CMS.
A client SHOULD request a specific format by adding a format specifier to the Accept
header. For example, to request a JSON response to a request for an article, the client
could include the following header:
By adhering to these property name guidelines JavaScript clients should be able to access
properties in JSON messages using dot notation and the exact same property names can be
used in both JSON and XML messages.
XML
● All property names SHOULD be camel-cased, ASCII strings using only alphanumeric
characters.
● The first character of each property name SHOULD be a letter. Subsequent
characters MAY be letters or digits.
Requesting a resource
Use the GET method to request a resource item or a list of resource items. For example, to
retrieve a list of users the client would issue this request
GET /users
Page 11
Recall that this is shorthand, for the purposes of clarity in this document, for the actual HTTP
request that would be sent. In reality, the first line of the request going over the wire would
be something like this
HTTP/1.1 200 OK
Date: Sun, 02 Dec 2012 22:05:40 GMT
Server: Apache/2.2.14 (Ubuntu)
Vary: Accept-Encoding
Keep-Alive: timeout=15, max=100
Content-Encoding: gzip
Content-Type: application/json
Connection: Keep-Alive
Etag: 0asj21309halskdjl
Content-Length: 124
Again, for the purposes of clarity in this document, such a response will be abbreviated to
200 OK with headers only listed if they are relevant to the discussion, together with a
description of the message body, often shortened for clarity. Other elements of the
response will be assumed.
A request for a resource name that is not recognised MUST result in a 404 Not found error
with a suitably informative error message body. However, a request for a list of (valid)
resources that happens to return an empty list MUST return a status of 200 OK because it is
not an error to return an empty list. A request for a specific resource item identified by an id
number in the request MUST return a 404 Not found error if the specifically identified
resource item does not exist.
GET /users/1234
will, assuming the resource item exists, result in a 200 OK response with a message body
containing the single resource item using the application/vnd.joomla.item.v1 media type. On
the other hand, a request for a list of resources, such as
GET /users
Resource names MAY be namespaced using a colon (“:”) to separate the namespace from
Page 12
the base resource name. For example, “joomla:articles” could be used to distinguish the
articles resource in the Joomla CMS from, say “my:articles”. Namespaces are defined in
[Curie] syntax and the server SHOULD include a definition of any namespaces used in a
response message in the curie object in the _links object of the message. For further
information see [item] and [list].
GET http://api.domain.com/arti
/articles cles succe
error
ss
200 OKContent-Type:
application/vnd.joomla.list.v1+js
on
Conditional requests
Server responses SHOULD include an ETag to identify the version of the resource or
resource collection returned. If the client needs to retrieve the same resource or collection
again and wants to improve efficiency then it can include the ETag in an If-None-Match
header and the server will respond with a 304 Not modified, but no message body, if the
resource or collection has not changed. If the resource has changed, which is determined
by the ETag no longer matching, then the resource or collection will be returned with a 200
OK exactly as if the client had not sent an If-None-Match header. Full details on the ETag
and If-None-Match headers can be found in [RFC2616].
Server responses SHOULD include a Last-Modified header to indicate when the data
included in the response was last amended. In the case of a collection of resource items,
the Last-Modified date will be the most recent of the last amended dates of the resource
items included in the collection. As with the ETag header, a client wishing to improve
efficiency can include an If-Modified-Since header in a GET request and expect to get a 304
Not modified status code and an empty message body if the last amended date of the
resource or collection pre-dates the If-Modified-Since date. Full details on the Last-Modified
and If-Modified-Since headers can be found in [RFC2616].
Note that using Last-Modified is less precise that using ETags because dates can only be
given to an accuracy of a single second. For that reason the ETag mechanism is to be
preferred.
The ETag mechanism is also used for the optimistic locking strategy as described in [item].
Page 13
GET /articlesIf-None-
Match:
http://api.domain.com/arti
k0d23jg0h234sdflIf-
cles/1234 succe
Modified-Since: 2013-06- error
02T11:54:00Z ss
200 OKContent-Type:
application/vnd.joomla.item.v1+j
son
Clients SHOULD NOT construct the URL using out-of-band information contained in this
specification, but instead SHOULD determine the URL by following a link from a previously
retrieved resource. Most likely this will be the root service resource which includes a list of
links to all the available resources. This loose coupling allows servers to dynamically move
the URL for creating new resources to different locations, for example to spread server load,
without breaking clients.
The media type of the POST request SHOULD be set to match that required by the resource
type being created, which will most likely be an extension of application/vnd.joomla.item.v1
with a format specifier and optional schema parameter. If the server does not recognise or
cannot reliably handle the media type in the request it SHOULD return a 400 Bad request
status code.
For example, creating a new article might look something like this
POST /articles
Content-Type: application/vnd.joomla.item.v1+json; schema=joomla:articles.v1
If the new resource is successfully created then the service MUST return a 201 Created
response.
The response SHOULD include a Content-Location header with the full absolute URL of the
Page 14
resource item that was just created.
POST /articlesContent-
Type:
application/vnd.joomla.ite http://api.domain.com/arti
m.v1+json; cles succe
error
schema=joomla:articles.v ss
201 CreatedContent-Location:
1{message-body}
http://api.domain.com/articles/92
8
201 Created
Content-Location: http://www.domain.com/api/v1/articles/98723
ETag: 098nsd09f2309as
Last-Modified: Sun, 27 Jan 2013, 10:29:20
Prefer: return=representation
then the server SHOULD also include a full representation in the message body of the
resource that was created, exactly as if the client had immediately made a GET request for
that item. The Prefer header is defined in [Snell].
POST /articles/1234
will also result in a 400 Bad request status being returned. A request to create a resource
item that already exists SHOULD result in a 400 Bad request status being returned.
Any fields in the request body that are not recognised SHOULD be ignored.
Updating a resource
Use a PUT request to update a resource. To avoid overwriting another client’s changes the
client SHOULD include the ETag from the resource being modified in an If-Match header. If
the resource has been changed by another client since being last retrieved, then the ETag
will no longer match and the service MUST return a 412 Precondition failed status. If the
Page 15
update succeeds then the service MUST return a 200 OK status together with a message
body containing a JSON-encoded representation of the resource exactly as it the client had
immediately made a GET request for the updated item.
Similarly, the client SHOULD also include an If-Unmodified-Since header. If the date/time
given indicates that the resource may have been modified since the client last retrieved it,
then the server MUST return a 412 Precondition failed status.
If the client omits both an If-Match header and an If-Unmodified-Since header then the
service MUST return a 400 Bad request status together with a suitable explanation of the
reason for the rejection. See later in this document for a description of error message body
format.
A PUT request to update a resource item that does not exist MUST result in a 404 Not found
error.
200 OK
PUT /articles
with a message body containing fields to update will update ALL articles. [Is this too
dangerous to support?]
Any fields in the request body that are not recognised SHOULD be ignored.
Deleting a resource
Use a DELETE request to delete a resource.
Page 16
If the resource specified for deletion does not exist then the server MUST return a 404 Not
found status.
If the resource is checked out by another user then the server MUST return a 400 Bad
request status and MUST NOT delete the resource. The response message body MUST
include a description of the reason for not deleting the resource.
If the client includes an If-Match header the server will check that the ETag matches before
deleting the resource and returning a 200 OK status. If the ETags do not match the service
MUST return a 412 Precondition failed status. If the client omits the If-Match header then
the server MUST always delete the resource and return a 200 OK status.
If a client wants to delete a resource without regard to any changes that may have been
made to it since it last retrieved it then include an If-Match: * header. The service MUST
NOT attempt to verify the ETag and MUST delete the resource even if it is checked out by
another user.
DELETE MUST be a "hard" delete that actually deletes the resource specified rather than
moving it to a trashed state. For a "soft" delete use the PUT method to change the state of
the resource item.
After a successful DELETE any subsequent GET on the same resource MUST return a 404
Not found status.
DELETE /articles
Page 17
DELETE /articles/1234If-Match: http://api.domain.com/article
34dlkj2l0fsd s/1234
success error
200 OK
Filtering requests
It would be very inefficient for a client to request all items in a resource and then have the
client filter out just the few that it needs as this might potentially entail transferring every
resource item over the wire to the client. It must be possible for the client to request just
those items that it needs by specifying one or more criteria for choosing those items. In
database terms this is like being able to give a WHERE clause to the service.
To filter requests, append a list of name/value pairs to the request. For example, to get the
featured articles only, use a request like this:
GET /articles?featured=true
Multiple criteria can be specified in the usual way. For example, to get only the featured
articles that are published use a request like this:
GET /articles?featured=true&state=published
A range of different comparison operators is available for use in filter expressions. See
Comparison operators for the full list.
Filtering on an object can only be done if a property name within the object is specified. This
is done by giving the path to the property as the field name. For example, filtering on the
author name in the articles resource would look like this:
GET /articles?metadata.createdBy.title=Joe+Bloggs
Page 18
Third-party developers need to be aware that field names must not collide with reserved
argument names. A table of reserved argument names may be found at the end of this
document.
Comparison operators
When filtering requests and when filtering fields in a partial response, a number of
comparison operators may be used. The following table gives the full list with some
examples.
Numerical =
comparison !=
>
>=
<
<=
Linked resources
Resources almost always have associations with other resources and this can easily be
represented using the form
/resource/identifier/resource
For example, the following will retrieve a list of articles associated with category id 625.
GET /categories/625/articles
Page 19
However, the temptation to extend this to deeper levels of hierarchy should be avoided if at
all possible. Where more resources need to be involved in a request it is almost always
better to put the additional complexity into the query part of the request rather than
increasing the complexity of the path segment.
Note that as a general design principle the server is responsible for maintaining referential
integrity.
One-to-many relationships
These can be navigated quite simply using the above form. For example, in Joomla an
article can belong to only category, so there is a one-to-many relationship between
categories and articles. Suppose that category id 5778 includes article ids 1234 and 5432.
Then these are some of the requests that the client could make regarding these objects,
together with their expected responses:
Category
5778
Article Article
1234 5432
Request Response
Page 20
GET /categories/5778/articles Media type: application/vnd.joomla.list.v1
Response will contain the collection of articles belonging to
category 5778. The collection will therefore contain
representations of articles 1234 and 5432.
The representation of article 1234 in the collection will
include these links:
● self: /articles/1234
● categories: /categories/5778
and the representation of article 5432 will include these
links:
● self: /articles/5432
● categories: /categories/5778
Many-to-many relationships
Many-to-many relationships can always be decomposed into a pair of one-to-many
relationships with an intermediate “mapping” entity, whether that entity actually exists in the
data model or not. It is RECOMMENDED that this mapping entity be given a name so that it
can be referred to in requests. This makes it easier to maintain the many-to-many
associations using the API and allows additional information to be added to the mapping
entity at some future date without breaking existing clients.
For example, suppose there is a pair of linked resources containing teams and players. A
player could be on many teams and a team consists of many players. To represent the
many-to-many relationship there must a resource that maps teams and players. Suppose
this is given the name players-teams. If there is a team with id 5778 which includes players
1234 and 5432, then we have something looking like this:
Team
5778
Playe Playe
r- r-
team team
6145 9427
Playe Playe
r r
1234 5432
These are some of the requests that the client could make regarding these objects, together
with their expected responses:
Page 21
Request Response
Suppose now that player 5432 joins a new team 839. Player 5432 now belongs to two
teams:
Page 22
Team Team
5778 839
Playe Playe
r r
1234 5432
The client would issue a POST request to create the new relationship. The format of the
POST message body is not defined here; refer to [item] for further details. The client would
issue the following request to represent this change:
Request Response
Page 23
Team Team
5778 839
Playe Playe
r- r-
team team
6145 3842
Playe Playe
r r
1234 5432
The client would issue the following request to represent this change:
Request Response
Partial responses
By default all appropriate fields in the representation of a resource item are returned by the
service whenever a client requests the resource item. However, to reduce the volume of
information returned it is possible for a client to request a more limited set of fields from the
resource by using the fields argument with a comma-separated list of field identifiers.
In the simplest case the field identifiers are just field names. For example, to obtain a list of
article titles and aliases only, the following request could be made
GET /articles?fields=title,alias
However, it is also possible to link to other resources, such as the category to which each
article belongs, by specifying the field name in the linked resource with the resource name
as a prefix, like this
GET /articles?fields=title,alias,categories.title
which will retrieve the title and alias for each article together with the title of the category to
which each article belongs.
If more than one field is being retrieved from a single linked resource then the following
shorthand form MAY be used
GET /articles?fields=categories(title,alias)
which will retrieve the title and alias for the category associated with each article.
Page 24
If all article fields are also to be included then this can be specified like this
GET /articles?fields=*,categories(title,alias)
GET /articles
GET /articles?fields=*
In many cases a resource will contain objects, such as link objects, that themselves have
fields. In such cases the fields within the object can be addressed in the same way that
other linked data resources can be addressed. For example, to select just the href field
within the createdBy link object in each article, use this
GET /articles?fields=metadata.createdBy.href
GET /articles/1234/categories?fields=articles
will return the category object to which article 1234 belongs with an embedded articles object
comprising a list of articles belonging to that category. The amount of data returned can be
reduced by selecting only the fields of interest. For example,
GET /articles/1234/categories?fields=articles(title,alias,metadata.createdBy.title)
Resource associations can be nested. No limit to the degree of nesting is given in this
specification but it is likely that some reasonable limit will be imposed by specific
implementations.
The number of items returned from a linked resource can be reduced by specifying that they
must match some selection criterion. For example, to select only those articles in a category
with a given author use something like this
Note that the metadata.createdBy.title field is not one of those returned in the array of
articles. To include it you would need to explicitly request it, like this
A range of different comparison operators is available for use in field condition expressions.
See Comparison operators for the full list.
Page 25
field-identifier = [ resource-path "/" ] field-name |
[ resource-path ] [ field-condition ] "(" field-list ")" |
*
resource-path = resource-name [ "/" resource-path ]
Search
It is possible to search across resource types using a special search API. The response
MUST always be a (possibly empty) list of resource items.
There are currently two possible search APIs available, each of which has a different range
of capabilities. Either, neither or both of the search APIs may be available on any particular
installation. In both cases a search request is initiated by submitting a POST request to the
relevant search URL.
Clients SHOULD NOT construct the URL using out-of-band information contained in this
specification, but instead SHOULD determine the URL by following a link from a previously
retrieved resource. This loose coupling allows servers to dynamically move the URL to
different locations, for example to spread server load, or change URL structure, without
breaking clients. Clients MUST perform the correct token substitutions if the link is defined
as a URI template [RFC6570].
The links provided by the server for access to search SHOULD be regarded as being
context-sensitive. For example, the links provided in the root resource are expected to
provide search across all resource types, whereas the links provided in the “articles”
resource will only provide search within the articles scope.
Clients MAY submit an empty request body if all the arguments required to perform the
search have been supplied as tokens in the URI template. If a request body is supplied then
one of the following Content-Type headers SHOULD be supplied
Content-Type: application/vnd.joomla.search.v1+json
Content-Type: application/vnd.joomla.search.v1+xml
Content-Type: application/json
Content-Type: application/xml
Generally the first request with a particular set of search criteria will return the first page of
possibly many pages of results. The _links object in the response will contain a pages link
which will be a URI template allowing ready access to all pages of results in the set. See the
Pagination section of the application/vnd.joomla. list.v1 specification.
Since linking to a page of search results is a common requirement it should be noted that a
GET request with a method=post argument is equivalent to a POST request with the post
variables coded as request arguments.
Page 26
Basic search
The original search that has been available in all versions of the Joomla CMS since the very
beginning, may be accessed via the API by following the “joomla:basicsearch” link, if it is
enabled.
{
“_links”: {
“joomla:basicsearch”: { “href”: “/basic-search{?q}”, “templated”: true }
}
}
the following request will look for the string “on a clear disk you can seek forever".
POST /basic-search?q=on+a+clear+disk+you+can+seek+forever
Content-Type: application/json
Smart Search
If Smart Search has been enabled then an extended search capability is available. Smart
Search may be accessed via the API by following the “joomla:smartsearch” link, if it is
enabled.
{
“_links”: {
“joomla:smartsearch”: { “href”: “/search{?q}”, “templated”: true }
}
}
then this request will look for the string “on a clear disk you can seek forever":
POST /search?q=on+a+clear+disk+you+can+seek+forever
Content-Type: application/json
The q request argument is no longer a simple search string. With Smart Search it becomes
a list of search terms, search expressions and logical operators. All search terms and
phrases are case-insensitive.
web services api Search for all items containing the terms “web” or “services”
or “api”.
Page 27
web or services or api Same as above.
“web services api” Search for the exact phrase “web services api”.
web and services Search for all items containing the terms “web” and
“services”.
web services not api Search for all items containing the terms “web” or “services”
but not “api”.
“web services” type:article Search for all articles containing the phrase “web services”.
Other possible search expressions are listed in the table
below.
Implementation note: In Joomla 3.0 the maximum length of a search phrase is 3 terms.
w1 When associated with the first date. May be “before”, “after” or “exact”.
w2 When associated with the second date. May be “before”, “after” or “exact”.
Smart Search also supports autocompletion, which is where a filtered drop-down containing
search terms and phrases is also supported. If autocompletion is enabled an additional link
relation will be added to the _links object, which might look like this one:
{
“_links”: {
“joomla:autocomplete”: { “href”: “/search{?q}&task=suggestion”, “templated”: true }
}
}
Page 28
Authentication
Although authentication is not required, the API is likely to at least support the standard
basic authentication mechanism [RFC2617]. Under this protocol a request for a resource
that requires authentication would get an initial response like this
401 Unauthorized
WWW-Authenticate: Basic realm ="Web API"
The service MAY send whatever realm string makes sense as its purpose is to assist the
client in choosing the correct credentials for the service. The client SHOULD then repeat the
request with the additional header
Error handling
Errors should always be mapped and returned using the standard HTTP return codes. Of
course, in the absence of an error condition a call to the API should return a status code in
the 2xx series. However, a limited number of additional codes may be returned when an
error condition arises. Developers should resist the temptation to add additional codes
because this can result in additional work for the calling application to decide how to handle
them.
400 - Bad request The request was malformed or could not be understood.
Error codes in the 400 series indicate that the calling
application did something wrong.
401 - Unauthorised The request was authenticated but failed to meet the access
requirements for the resource or operation requested.
412 - Precondition failed Either the ETag or Last-Modified dates did not match
500 - Internal server error This is a catch all error code that should only be used when
no more specific code is available. Errors in the 500 series
indicate that the API did something wrong. A 5xx series error
Page 29
code is never the client's fault and therefore it is reasonable
for the client to repeat the request in the hope of getting a
different response.
In addition to the HTTP status code, the server MAY also return a message body containing
a JSON-encoded description of the error condition. The error message should be in plain
language and should provide as much information as possible so as to assist users in
determining the cause of the problem. The format for error messages is as per [Nottingham]
and they have a media type of application/api-problem+json.
Additional fields MAY be added where necessary to help users to understand the nature of
the specific problem encountered.
For the Joomla CMS the describedby field will point to a set of English wiki pages with the
following structure:
http://docs.joomla.org/API_errors/{APIVersion}/{errorString}
For example,
http://docs.joomla.org/API_errors/v1/Content_type_not_acceptable
Users are encouraged to add additional helpful information to these pages at any time. The
ability to cross-link to equivalent non-English pages will also be supported.
Third party extension developers will be able to provide URL's that link to their own websites.
Error messages SHOULD be capable of being localised with English (en-GB) being used as
the fallback if a particular message is not available in the language requested. The Accept-
Language header MUST be used to determine the most appropriate language for the error
Page 30
message.
Adding a callback argument to a request will cause the service to return the JSON data
wrapped in a JavaScript function callback. For example, a request such as this
GET /users?callback=myFunction
Furthermore, the service MUST change the Content-Type header from application/json to
application/javascript.
Note that there may be difficulties when using this technique is some situations due to
restrictions often imposed on GET requests such as strictly limiting URL length.
Implementation Notes
It might be reasonable to apply rate limits to API calls so as to prevent abuse of the service,
however this is beyond the scope of this document.
This standard does not specify the entry point to the API within a Joomla installation. Site
owners SHOULD be free to choose where in the site's filesystem they want to situate the
API. For example, the API could be located in a subdirectory called /api under the web root
or it might equally be hosted in a separate subdomain such as http://api.example.com.
Page 31
accept Exactly equivalent to the Accept header field. Overrides the Accept
header field if both are present.
fields Defines the fields required by the client in a partial response request.
method Allows clients to specify the HTTP verb required on platforms that do
not allow the client to use the correct HTTP verb explicitly.
Page 32
sort Sort order.
References
base application/vnd.joomla.base.v1 media type specification (second draft)
Chris Davenport
https://docs.google.com/a/joomla.org/document/d/11SqH-
daKQV9SrFBMEpopjBk3vM1USIHnFWZB9rjJB94/edit
Page 33
Nottingham Problem Details for HTTP APIs
M. Nottingham
http://tools.ietf.org/html/draft-nottingham-http-problem-02
RFC4627 The application/json Media Type for JavaScript Object Notation (JSON)
D. Crockford
http://www.ietf.org/rfc/rfc4627
Page 34
1bub4sa_BhsKfzAmX21eG-FM/edit
Document History
15 Dec 2012 Minor additions and amendments. Imported relevant parts of Kelly on
URI object definition and removed references to same.
16 Dec 2012 Altered link object definition to more closely correspond with RFC5988.
Flattened hierarchy and removed links object definition. Merged
suggested amendments to pagination variables.
18 Dec 2012 Added image and metadata object definitions. Added “browser”
property to link object. Expanded Joomla CMS 3.x information.
Page 35
property to link objects.
18 Jan 2013 Added slightly more strict requirement for property names.
22 Jan 2013 Added table of reserved query arguments. Added note and references
about namespaced resource names.
27 Jan 2013 Added more detail on POST for creating new resources. Added note
on Prefer header and reference to [Snell].
9 Feb 2013 Improved some text. Expanded the section on linked resources.
Added more diagrams. Dropped application/vnd.joomla.error.v1 in
favour of application/api-problem+json ([Nottingham]).
Page 36