Using the Guillotina API¶
Before we start using the Guillotina API, let’s get us some test data to play with.
Using the testdata
command, we’ll populate our database with some data from
wikipedia.
g testdata --per-node=5 --depth=2 --container=container
Interacting with the API¶
You can use whatever you’d like but this training will mention use of Postman.
Open up Postman and do a GET
on http://localhost:8080/db/container
with the username root
and password root
for basic auth.
We can not necessarily go over every single API but will touch on a few and give a general understanding of how to explore and use the API.
Creating content¶
To create content, do a POST
request on a container or folder object.
-
POST
/
(db)/
(container)¶ Add new resouce inside this container resource
- Permission: guillotina.AddContent
- Context: guillotina.interfaces.content.IResource
http
POST /db/container HTTP/1.1 Accept: application/json Authorization: Basic cm9vdDpyb290 { "@type": "Item", "id": "foobar5" }
curl
curl -i -X POST http://nohost/db/container -H 'Accept: application/json' --data-raw '{ "@type": "Item", "id": "foobar5" }' --user root:root
httpie
echo '{ "@type": "Item", "id": "foobar5" }' | http POST http://nohost/db/container Accept:application/json -a root:root
response
HTTP/1.1 201 OK Content-Type: application/json Location: http://localhost/db/container/foobar5 { "@id": "http://localhost/db/container/foobar5", "@name": "foobar5", "@type": "Item", "@uid": "bf6|f13d2535731443b492102e832eee65df" }
Status Codes: - 200 OK – Resource data
- 401 Unauthorized – You are not authorized to perform the operation
- 404 Not Found – The resource does not exist
Adding behaviors¶
To add a dynamic behavior, we use the @behavior
endpoint.
-
PATCH
/
(db)/
(container)/
(content)/@behaviors
¶ Add behavior to resource
- Permission: guillotina.ModifyContent
- Context: guillotina.interfaces.content.IResource
http
PATCH /db/container/foobar5/@behaviors HTTP/1.1 Accept: application/json Authorization: Basic cm9vdDpyb290 { "behavior": "guillotina.behaviors.attachment.IAttachment" }
curl
curl -i -X PATCH http://nohost/db/container/foobar5/@behaviors -H 'Accept: application/json' --data-raw '{ "behavior": "guillotina.behaviors.attachment.IAttachment" }' --user root:root
httpie
echo '{ "behavior": "guillotina.behaviors.attachment.IAttachment" }' | http PATCH http://nohost/db/container/foobar5/@behaviors Accept:application/json -a root:root
response
HTTP/1.1 200 OK Content-Type: application/json {}
Status Codes: - 200 OK – Successfully added behavior
- 401 Unauthorized – You are not authorized to perform the operation
- 404 Not Found – The resource does not exist
- 412 Precondition Failed – Behavior already assigned here
Uploading files¶
Simple file uploads can be done with the @upload
endpoint.
-
PATCH
/
(db)/
(container)/
(content)/@upload/file
¶ - Permission: guillotina.ModifyContent
- Context: guillotina.interfaces.content.IResource
http
PATCH /db/container/foobar5/@upload/file HTTP/1.1 Accept: application/json Authorization: Basic cm9vdDpyb290 <text data>
curl
curl -i -X PATCH http://nohost/db/container/foobar5/@upload/file -H 'Accept: application/json' --data-raw '<text data>' --user root:root
httpie
echo '<text data>' | http PATCH http://nohost/db/container/foobar5/@upload/file Accept:application/json -a root:root
response
HTTP/1.1 200 OK Content-Type: application/json {}
Status Codes: - 401 Unauthorized – You are not authorized to perform the operation
- 404 Not Found – The resource does not exist
Then, to download the file, use the @download
endpoint.
-
GET
/
(db)/
(container)/
(content)/@download/file
¶ - Permission: guillotina.ViewContent
- Context: guillotina.interfaces.content.IResource
http
GET /db/container/foobar5/@download/file HTTP/1.1 Accept: application/json Authorization: Basic cm9vdDpyb290
curl
curl -i http://nohost/db/container/foobar5/@download/file -H 'Accept: application/json' --user root:root
httpie
http http://nohost/db/container/foobar5/@download/file Accept:application/json -a root:root
response
HTTP/1.1 200 OK Accept-Ranges: bytes Content-Disposition: attachment; filename="f16fe4b800dd435aa2cb8e86d417e2f6" Content-Length: 11 Content-Type: application/octet-stream <text data>
Status Codes: - 401 Unauthorized – You are not authorized to perform the operation
- 404 Not Found – The resource does not exist
Uploading files with TUS¶
Guillotina also supports the TUS protocol using the @tusupload
endpoint. The
TUS protocol allows you to upload large files in chunks and allows you to have
resumable uploads.
First, initialize the TUS upload with a POST
-
POST
/
(db)/
(container)/
(content)/@tusupload/file
¶ - Permission: guillotina.ModifyContent
- Context: guillotina.interfaces.content.IResource
http
POST /db/container/foobar5/@tusupload/file HTTP/1.1 Accept: application/json Authorization: Basic cm9vdDpyb290 TUS-RESUMABLE: 1 UPLOAD-LENGTH: 22
curl
curl -i -X POST http://nohost/db/container/foobar5/@tusupload/file -H 'Accept: application/json' -H 'Tus-Resumable: 1' -H 'Upload-Length: 22' --user root:root
httpie
http POST http://nohost/db/container/foobar5/@tusupload/file Accept:application/json Tus-Resumable:1 Upload-Length:22 -a root:root
response
HTTP/1.1 201 OK Content-Type: application/json Location: http://localhost/db/container/foobar5/@tusupload/file Tus-Resumable: 1.0.0 {}
Status Codes: - 401 Unauthorized – You are not authorized to perform the operation
- 404 Not Found – The resource does not exist
Next, upload the chunks(here we’re doing chunks):
-
PATCH
/
(db)/
(container)/
(content)/@tusupload/file
¶ - Permission: guillotina.ModifyContent
- Context: guillotina.interfaces.content.IResource
http
PATCH /db/container/foobar5/@tusupload/file HTTP/1.1 Accept: application/json Authorization: Basic cm9vdDpyb290 TUS-RESUMABLE: 1 Upload-Offset: 0 <text data>
curl
curl -i -X PATCH http://nohost/db/container/foobar5/@tusupload/file -H 'Accept: application/json' -H 'Tus-Resumable: 1' -H 'Upload-Offset: 0' --data-raw '<text data>' --user root:root
httpie
echo '<text data>' | http PATCH http://nohost/db/container/foobar5/@tusupload/file Accept:application/json Tus-Resumable:1 Upload-Offset:0 -a root:root
response
HTTP/1.1 200 OK Content-Type: application/json Tus-Resumable: 1.0.0 Upload-Offset: 11 {}
Status Codes: - 401 Unauthorized – You are not authorized to perform the operation
- 404 Not Found – The resource does not exist
And final chunk:
-
PATCH
/
(db)/
(container)/
(content)/@tusupload/file
¶ - Permission: guillotina.ModifyContent
- Context: guillotina.interfaces.content.IResource
http
PATCH /db/container/foobar5/@tusupload/file HTTP/1.1 Accept: application/json Authorization: Basic cm9vdDpyb290 TUS-RESUMABLE: 1 Upload-Offset: 11 <text data>
curl
curl -i -X PATCH http://nohost/db/container/foobar5/@tusupload/file -H 'Accept: application/json' -H 'Tus-Resumable: 1' -H 'Upload-Offset: 11' --data-raw '<text data>' --user root:root
httpie
echo '<text data>' | http PATCH http://nohost/db/container/foobar5/@tusupload/file Accept:application/json Tus-Resumable:1 Upload-Offset:11 -a root:root
response
HTTP/1.1 200 OK Content-Type: application/json Tus-Resumable: 1.0.0 Tus-Upload-Finished: 1 Upload-Offset: 22 {}
Status Codes: - 401 Unauthorized – You are not authorized to perform the operation
- 404 Not Found – The resource does not exist
Unknown upload size¶
Guillotina’s TUS implementation has support for the Upload-Defer-Length
header.
This means you can upload files with an unknown final upload size.
In order to implement this correctly, you will need to provide the
Upload-Defer-Length: 1
header and value on the initial POST to start the TUS
upload. You are then not required to provide the UPLOAD-LENGTH
header.
Then, before or on your last chunk, provide a UPLOAD-LENGTH
value to let
TUS know the upload can not finish.
Simultaneous TUS uploads¶
Guillotina’s TUS implementation also attempts to prevent simultaneous uploaders.
If two users attempt to start an upload on the same object + field at the same time, a 412 error will be thrown. Guillotina tracks upload activity to detect this. If there is no activity detected for 15 seconds with an unfinished TUS upload, no error is thrown.
To override this, send the TUS-OVERRIDE-UPLOAD: 1
header.
Modifying permissions¶
The @sharing
endpoint is available to inspect and modify permissions on an object.
-
GET
/
(db)/
(container)/
(content)/@sharing
¶ Get sharing settings for this resource
- Permission: guillotina.SeePermissions
- Context: guillotina.interfaces.content.IResource
http
GET /db/container/foobar5/@sharing HTTP/1.1 Accept: application/json Authorization: Basic cm9vdDpyb290
curl
curl -i http://nohost/db/container/foobar5/@sharing -H 'Accept: application/json' --user root:root
httpie
http http://nohost/db/container/foobar5/@sharing Accept:application/json -a root:root
response
HTTP/1.1 200 OK Content-Type: application/json { "local": { "roleperm": {}, "prinperm": {}, "prinrole": { "root": { "guillotina.Owner": "Allow" } } }, "inherit": [ { "@id": "http://localhost/db/container", "roleperm": {}, "prinperm": {}, "prinrole": { "root": { "guillotina.ContainerAdmin": "Allow", "guillotina.Owner": "Allow" } } } ] }
Status Codes: - 200 OK – All the sharing defined on this resource
- 401 Unauthorized – You are not authorized to perform the operation
- 404 Not Found – The resource does not exist
To modify, we use the same endpoint but with a POST
.
-
POST
/
(db)/
(container)/
(content)/@sharing
¶ Change permissions for a resource
- Permission: guillotina.ChangePermissions
- Context: guillotina.interfaces.content.IResource
http
POST /db/container/foobar5/@sharing HTTP/1.1 Accept: application/json Authorization: Basic cm9vdDpyb290 { "prinperm": [ { "principal": "foobar", "permission": "guillotina.ModifyContent", "setting": "Allow" } ] }
curl
curl -i -X POST http://nohost/db/container/foobar5/@sharing -H 'Accept: application/json' --data-raw '{ "prinperm": [ { "principal": "foobar", "permission": "guillotina.ModifyContent", "setting": "Allow" } ] }' --user root:root
httpie
echo '{ "prinperm": [ { "principal": "foobar", "permission": "guillotina.ModifyContent", "setting": "Allow" } ] }' | http POST http://nohost/db/container/foobar5/@sharing Accept:application/json -a root:root
response
HTTP/1.1 200 OK Content-Type: application/json {}
Status Codes: - 200 OK – Successfully changed permission
- 401 Unauthorized – You are not authorized to perform the operation
- 404 Not Found – The resource does not exist
There are three types of permission settings you can modify:
- prinperm: principal + permission
- prinrole: principal + role
- roleperm: role + permission
Each change can use the following settings:
- Allow : you set it on the resource and the children will inherit
- Deny : you set in on the resource and the children will inherit
- AllowSingle : you set in on the resource and the children will not inherit
- Unset : you remove the setting
Exploring the API with OpenAPI¶
In the previous step, we installed guillotina.contrib.swagger
. With OpenAPI, we can
inspect any context and explore the API.

Visit http://localhost:8080/@docs

Click the Authorize
button
The top URL setting is what the current context is that you’re exploring the API
on. If you create content at /db/container/foobar
and want to explore that
content’s API, you should change the URL. Different content types will have
different services available.
References