Rich Javascript frontends, mobile applications and third party software need an API to interact with your CMS. Let’s give Plone one!

plone.restapi: making Plone machine-friendly

Rich Javascript frontends, mobile applications and third party software need an API to interact with your CMS. Let’s give Plone one!

At the PLOG 2014 in Sorrento, a discussion was started among participants about providing Plone with an API accessible by external systems. This discussion ended up in the creation of the plone.restapi package, which contains the embryo of a machine-friendly interface for Plone in the form of a narrative documentation.

What is it for?

In the initial phase we started out by brainstorming about the use cases that our interface must cater to: alternative frontends (e.g. an AngularJS frontend) and external services that wish to integrate with Plone (e.g. an application that needs to retrieve some content).


The first important decision we made was between an RPC interface or a REST interface: this is a basic choice that dramatically affects the design of the API. While RPC interfaces have been hugely popular in the past (SOAP anyone?) and Zope already offers a basic implementation (XML-RPC) we decided that such an API would not be optimal, as REST interfaces are becoming the norm and because Plone is already quite REST oriented (e.g. the concept of traversal), and we unanimously decided to go the REST way.

What we did once we decided to go the REST way was to make sure that Zope could handle HTTP verbs different from GET or POST: a very simple and crude proof-of-concept is included in the same repository of the documentation (it uses a traversal and request marking to avoid falling into the WebDAV case of the ZPublisher) and gave us the confidence that yes, PUT, DELETE and PATCH are possible in Zope.

We also selected a few resources to learn a bit more about REST APIs: Leonard Richardson’s RESTful Web APIs book, the REST cookbook website, and we also looked at Python EVE as an example.

Machine interfaces are like the Tables of the law: once published, you can’t change them without causing uproar, vocal opposition and general breakage all over the place. Therefore, learning from the mistakes of the past, we elected to provide our API with a version: clients elect which version to choose and any breaking changes spawn a new version of the API, while the old version is still retained and functional. This way, clients and external services that can’t or won’t update can still function using the old API (and then hopefully migrate with time).

Another decision we agreed upon early on was that the format in which the API talks would be pluggable. That is, the API initially would speak plain JSON, but an extension mechanism (dubbed “dialects”) would allow the client to select from a number of available formats via the Accept header. This is important because REST interfaces have a core principle called HATEOAS (Hypermedia as the engine of application state) and plain JSON doesn’t quite match the definition. There is a semantic, schema enabled version of JSON (JSON-LD) that would be appropriate, but it was deemed as too complex to focus on in the initial stage. Therefore the “dialects” mechanism allows us to add more data formats over time without forcing a choice on the users.

The scope of the API

We also took time to identify what operations our API should provide in its initial incarnation: we decided to stick with the very basic core of Plone functionalities, plus a few things that are API specific.

In order, these are:

  • CRUD operations on content (creating, modifying, deleting content, and content listing for folders)
  • Search
  • Workflow (changing state on content)
  • Security (reading permissions and roles, assigning local roles)
  • Introspection (read only operations):
    • Type schemas (supporting dexterity and the concept of behaviors)
    • Users (list registered users, search users, get user information)
    • Groups (list, search, information and membership)
    • Roles (listing, information about permissions associated with roles globally)
    • API (what versions are available, available dialects)

Where to go from here?

As we said at the beginning, we currently have a very embryonal documentation, and no implementation. The first focus is to finish the missing area of the documentation (and expand the areas that need to be expanded) and then start in earnest with the actual implementation.

The repository is open for everyone to suggest improvements to the current status of the documentation via pull requests (so that changes get a chance to be discussed before merging). Once the documentation is complete (no more TODOs) a sprint will be planned to get on with the actual implementation.

Please let us know what you think!

Share this on

Share |

On same topics


comments powered by Disqus