JSON API

This page documents the JSON API provided by cubicweb-jsonschema under the application/json content type.

Collection resources (entities)

>>> resp = client.get('/author/',
...                   headers={'accept': 'application/json'})
>>> print(resp)  
Response: 200 OK
Allow: GET, POST
Content-Type: application/json
Link: </>; rel="up", </author/schema>; rel="describedby"; type="application/schema+json"
[
    {
        "id": "...",
        "type": "author",
        "title": "Ernest Hemingway"
    }
]

Notice the Allow: POST header, meaning the server would accept the creation of entity of type Author at the /author endpoint. So let’s add some Author entities:

>>> resp = client.post_json('/author/', {'name': 'Victor Hugo'},
...                         headers={'Accept': 'application/json'})
>>> print(resp)  
Response: 201 Created
Content-Type: application/json
Location: https://localhost:80/author/.../
{
    "name": "Victor Hugo"
}
>>> resp = client.post_json('/author/', {'name': 'Aldous Huxley'},
...                         headers={'Accept': 'application/json'})
>>> print(resp)  
Response: 201 Created
Content-Type: application/json
Location: https://localhost:80/author/.../
{
    "name": "Aldous Huxley"
}

Now we have something in the author collection:

>>> resp = client.get('/author/',
...                   headers={'accept': 'application/json'})
>>> print(resp)  
Response: 200 OK
Allow: GET, POST
Content-Type: application/json
Link: </>; rel="up", </author/schema>; rel="describedby"; type="application/schema+json"
[
    {
        "type": "author",
        "id": "...",
        "title": "Aldous Huxley"
    },
    {
        "type": "author",
        "id": "...",
        "title": "Victor Hugo"
    },
    {
        "type": "author",
        "id": "...",
        "title": "Ernest Hemingway"
    }
]

Single entity resource

To create an entity of type Author, we POST on /author endpoint:

>>> resp = client.post_json('/author/',
...                         {'name': 'Aldous Huxley'},
...                         headers={'Accept': 'application/json'})
>>> print(resp)  
Response: 201 Created
Content-Type: application/json
Location: https://localhost:80/author/.../
{
    "name": "Aldous Huxley"
}

We can retrieve the newly created resource by following the Location header URL:

>>> url = resp.location
>>> resp = client.get(url, headers={'Accept': 'application/json'})
>>> print(resp)  
Response: 200 OK
Content-Type: application/json
Link: </author/>; rel="up"; title="Author_plural", </author/.../schema>; rel="describedby"; type="application/schema+json"
{
    "name": "Aldous Huxley"
}

In case of invalid input data, we get a meaningful error message following rfc-7807.

>>> resp = client.post_json('/author/', {}, status=422,
...                         headers={'Accept': 'application/json'})
>>> print(resp)  
Response: 422 Unprocessable Entity
Content-Type: application/problem+json; charset=UTF-8
{
    "status": 422,
    "title": "Unprocessable Entity",
    "invalid-params": [{
        "reason": "required attribute",
        "name": "name-subject"
    }]
}

To update an entity, we need to PUT the resource:

>>> resp = client.put_json(url, {'name': 'Aldous Leonard Huxley'},
...                        headers={'Accept': 'application/json'})
>>> print(resp)  
Response: 200 OK
Content-Type: application/json
Location: https://localhost:80/author/.../
{
    "name": "Aldous Leonard Huxley"
}

Finally we can delete an entity:

>>> resp = client.delete(url)
>>> print(resp)
Response: 204 No Content

>>> resp = client.get('/author/',
...                   headers={'accept': 'application/json'})
>>> print(resp)  
Response: 200 OK
Allow: GET, POST
Content-Type: application/json
Link: </>; rel="up", </author/schema>; rel="describedby"; type="application/schema+json"
[
    {
        "id": "...",
        "type": "author",
        "title": "Ernest Hemingway"
    }
]

Entity workflow

Entities’ workflow can be handled through the JSON API from the /<etype>/<eid>/workflow-transitions/ endpoint. It is possible to both get already passed workflow transitions and to add new transition to an entity.

To illustrate, this we’ll work with a UserAccount entity for which the workflow consists of activate and deactivate transitions.

First, let’s create such an entity:

>>> r = client.post_json('/useraccount/', {'username': 'tommy'},
...                      headers={'Accept': 'application/json'})
>>> print(r)  
Response: 201 Created
Content-Type: application/json
Location: https://localhost:80/useraccount/.../
{
  "username": "tommy",
  "in_state": "created"
}

We can get the workflow transitions for the entity (there’s none currently) as follows:

>>> r = client.get('/useraccount/tommy/workflow-transitions',
...                headers={'Accept': 'application/json'})
>>> print(r)  
Response: 200 OK
Content-Type: application/json
Link: </useraccount/.../workflow-transitions/schema>; rel="describedby"; type="application/schema+json"
[]

To add a new transition (i.e. change the workflow state), we POST to the workflow-transitions route the name of the transition and optionally a comment:

>>> r = client.post_json('/useraccount/tommy/workflow-transitions',
...                      {'name': 'activate', 'comment': 'Tommy is in'},
...                      headers={'Accept': 'application/json'})
>>> print(r)
Response: 204 No Content

Finally, we can get back the list of transitions:

>>> r = client.get('/useraccount/tommy/workflow-transitions',
...                headers={'Accept': 'application/json'})
>>> print(r)  
Response: 200 OK
Content-Type: application/json
Link: </useraccount/.../workflow-transitions/schema>; rel="describedby"; type="application/schema+json"
[
  {
    "id": "...",
    "title": "Tommy is in",
    "type": "trinfo"
  }
]