RFC: Using the JSON API specification for Neos services

Hi folks and sorry for digging out this old thread.

As a little disclaimer: The reason to use HTML as Hypermedia format originated in an idea of Jon Moore (one of the Hypermedia gurus out there).
I still find the idea strikingly persuasive but I also see some drawbacks at least with todays constraints.

In the meantime I played a lot around with different APIs and had the chance to test different media types in complex scenarios.

Recently I had a close look at JSON API. I had high expectations that this would finally end the “API format wars” given it’s written by some very clever REST experts.
I have to admit: I didn’t get along with it very well (and I really tried!).

To cut a long story short: My favorite is currently still HAL as it seems to hit a good balance between pragmatic and over-sophisticated.
Regarding hypermedia controls: Yes, HAL is missing a notion of HTTP method for links. But so is JSON API. And I don’t think it’s important – at least not until clients get so smart that they really only need the base URL of the API and explore all of their logic from there.
And there are extensions allowing for specifying forms including method and payload definition if that’s needed.

Having written all this I think that our main issue & challenge is to find a good abstraction level for our APIs.
I’d especially suggest not to fall into the CRUD-trap that will lead to high coupling and very complex code (as we already experience today).
I liked the idea of combining REST APIs with a CQRS-kind-of-style, described in these slides: http://de.slideshare.net/fatmuemoo/cqrs-api-v2

A (very simplified) API for the CR could look a bit like this:

{
  "_links": {
    "self": {
      "href": "/api/nodes"
    },
    "curies": [
      {
        "href": "https://neos.io/rels/{rel}",
        "name": "neos",
        "templated": true
      }
    ],
    "neos:create": {
      "href": "/api/nodes",
      "rel": "command",
      "title": "Create new node"
    }
  },
  "_embedded": {
    "neos:node": [
      {
        "id": "36a63168-2042-8ef7-3787-4a215f4dff75",
        "type": "Some:Node.Type",
        "properties": {
          "text": "Some Text"
        },
        "_links": {
          "neos:hide": {
            "href": "/api/nodes/36a63168-2042-8ef7-3787-4a215f4dff75/hide",
            "rel": "command",
            "title": "Hide this node"
          },
          "neos:move": {
            "href": "/api/nodes/36a63168-2042-8ef7-3787-4a215f4dff75/move",
            "rel": "command",
            "title": "Move this node"
          }
        }
      }
    ]
  }
}

The nice thing with this is that we could just omit the “command links” on the server if the current user hasn’t got the required privileges. The client / UI wouldn’t have to know about those, it would only show the “Hide”-Button if the neos:hide relation is found…