Philosophy
Medium
A medium
is a multimedia document (e.g. an audio file, an image or a video file).
attributes | type |
---|---|
name |
String |
url |
String |
description |
free |
history |
list |
id_corpus |
id |
Corpus
A corpus
is simply a collection of media
(e.g. all eight Harry Potter movies) – nothing more.
attributes | type |
---|---|
name |
String |
description |
free |
history |
list |
permissions |
dict |
Fragment
A fragment
is a part of a medium
(e.g. a rectangular area of an image or a temporal segment of an audio file).
A fragment
can be anything – be creative!
Annotation
An annotation
is a fragment
and its associated metadata
(e.g. the name of the person whose face is covered by the rectangular area).
Once again, a metadata
can be anything – be creative!
attributes | type |
---|---|
fragment |
free |
data |
free |
history |
list |
id_layer |
id |
id_medium |
id |
Layer
A layer
is simply a collection of annotations
sharing the same fragment
type and metadata
type.
attributes | type |
---|---|
name |
String (lowercase) |
description |
free |
fragment_type |
free |
data_type |
free |
history |
list |
permissions |
dict |
id_corpus |
id |
User
A user
is a person with an account on the Camomile platform.
attributes | type |
---|---|
username |
String (lowercase, unique) |
description |
free |
role |
“user” or “admin” |
Group
A group
is simply a set of users
– how extraordinary!
attributes | type |
---|---|
name |
String (lowercase, unique) |
description |
free |
users |
list |
Queue
A queue
is a list of items
attributes | type |
---|---|
name |
String (lowercase, unique) |
description |
free |
list |
list of items |
Server
The Camomile server is available on Github.
Installation
The recommended way to install and run the Camomile server is using Docker.
MongoDB
It relies on MongoDB for storing annotations.
$ export CMML_DB="/path/to/the/database"
$ docker run -d \
-v $CMML_DB:/data/db \
--name my_mongodb dockerfile/mongodb
Camomile REST API
Once the MongoDB container is up and running, the NodeJS Camomile server can use it as storage backend.
$ export CMML_MEDIA="/path/to/media/files"
$ docker run -d -P \
-v $CMML_MEDIA:/media \
-e ROOT_PASSWORD="R00t.p455w0rd" \
--link my_mongodb:mongodb \
--name camomile camomile/api
$ echo "Camomile server is now available at `docker port camomile 3000`"
Clients
Python
$ pip install camomile
The Python Camomile client is available on Github.
It can be installed easily using pip
package manager.
Javascript
<script type="text/javascript" src="camomile.js"></script>
<script type="text/javascript" src="fermata.js"></script>
The Javascript Camomile client is available on Github.
To use it in your webapp, you need to include both camomile.js
and fermata.js
.
Reference
Foreword
CRUD REST API
CAMOMILE server follows the conventional REST API for CRUD (Create, Read, Update, Delete) data access. For a given resource (either corpus, medium, layer, annotation), the correspondance with HTTP commands and Python or Javascript interface is as follows.
Action | HTTP command | Python/Javascript interface |
---|---|---|
Create | POST /resource | .createResource(…) |
Read | GET /resource/:id_resource |
.getResource(:id_resource ) |
Update | PUT /resource/:id_resource |
.updateResource(:id_resource ,…) |
Delete | DELETE /resource/:id_resource |
.deleteResource(:id_resource ) |
Users and groups
- a ‘root’ user is created when the server is launched; associated password is configured at launch time. The 'root’ user can perform all actions and should only be used for creating other users.
- users with 'admin’ role are the only ones allowed to create users, groups, corpora and queues. 'root’ has 'admin’ role and can create other 'admin’ users.
Permissions
PUT /corpus/:id_corpus/user/:id_user HTTP/1.1
{"right":3}
client.setCorpusPermissions(id_corpus, client.ADMIN, user=id_user)
client.setCorpusPermissions(id_corpus, client.WRITE, user=id_user)
client.setCorpusPermissions(id_corpus, client.READ, group=id_group)
Camomile.setCorpusPermissionsForUser(
id_corpus, id_user, Camomile.ADMIN, callback);
Camomile.setCorpusPermissionsForUser(
id_corpus, id_user, Camomile.WRITE, callback);
Camomile.setCorpusPermissionsForGroup(
id_corpus, id_group, Camomile.READ, callback);
The Camomile platform handles permissions: users may access only the resources for which they have enough permission.
Three levels of permissions are supported:
3 - ADMIN
admin permissions to the resource2 - WRITE
edition permissions to the resource1 - READ
read-only
Annotations
inherit permissions from the layer
they belong to.
Media
inherit permissions from the corpus
they belong to.
Permissions needed for the CRUD actions are summarized in the table below
Corpus | Permission needed |
---|---|
C | 'admin’ role |
R | >= READ to the corpus |
U/D | ADMIN to the corpus and 'admin’ role |
Medium | Permission needed |
---|---|
C/U | ADMIN to the corpus |
R | >= READ to the corpus |
D | ADMIN to the corpus |
Layer | Permission needed |
---|---|
C | >= WRITE to the corpus |
R | >= READ to the layer |
U/D | ADMIN to the layer |
Annotation | Permission needed |
---|---|
C/U/D | >= WRITE to the layer |
R | >= READ to the layer |
User | Permission needed |
---|---|
C/U/D | 'admin’ role |
R | authenticated user |
Group | Permission needed |
---|---|
C/U | 'admin’ role |
R | authenticated user |
D | 'root’ user |
Queue | Permission needed |
---|---|
C | 'admin’ role |
R | WRITE to the queue (destructive access) |
U/D | ADMIN to the queue |
- a user with 'admin’ role can create a corpus; (s)he becomes owner of the corpus and can share this ownership with selected users
- a corpus-owner (3-C = ADMIN permission on the corpus) can manage the corpus, its permissions and the associated media.
- a corpus-writer (2-C = WRITE permission on the corpus) can create layers in the corpus; (s)he becomes owner of the layer and can manage the permissions
- a layer-owner (3-L = ADMIN permission on the layer) can manage the layer, its permissions and the associated annotations.
- a layer-writer (2-L = WRITE permission on the layer) can create and edit annotations
- a layer-reader (1-L = READ permission on the layer) can only read annotations - for access to the corpus description and media (s)he should also generally get corpus-reader (1-C) permissions
- an authenticated user has no access to a resource until (s)he is specifically granted permission to it.
Resource ID
corpora = client.getCorpora()
id_corpora = client.getCorpora(returns_id=true)
assert corpora[0]._id == id_corpora[0]
client.getCorpora(
function(id_corpora) {
do_something_with(id_corpora);
},
{returns_id: True}
);
Each resource is given a unique identifier (_id
) by MongoDB upon creation.
The default behavior of most entry points is to return the complete resource, rather than just its _id
.
However, methods of the Python and Javascript clients support the returns_id
optional parameter.
Setting it to true
will return the resource MongoDB _id
instead of the complete resource.
Filters
GET /corpus?name='my%20corpus' HTTP/1.1
corpora = client.getCorpora(name='my corpus')
assert corpora[0].name == 'my corpus'
client.getCorpora(
function(corpora) {
},
{filter: {name: 'my corpus'}}
);
Most get{Resource}
methods (e.g. getCorpora
, getLayers
, …) support filtering by resource attribute.
History
GET /corpus?history=on HTTP/1.1
corpus = client.getCorpus(id_corpus, history=True)
do_something_with(corpus.history)
client.getCorpus(
id_corpus,
function (corpus) {
do_something_with(corpus.history);
},
{history: True}
);
The API keeps track of all changes made to corpora, media, layers and annotations, in a dedicated history
attribute.
The history
is simply a list of updates that were applied to the resource.
Each update has the following attributes:
date
: when the resource has changedid_user
: which user applied the changechanges
: the actual modification
However, to avoid sending what may become a very large amount of data with every request, the default behavior is to not send history
.
If you really want to get the history, you need to ask for it explicitely to get it.
Authentication
login
POST /login
DATA PARAMETERS
Key | Type | Description |
---|---|---|
username | String | The user name (required) |
password | String | The password (required) |
POST /login HTTP/1.1
{'username': 'johndoe', 'password': 'secretpassword'}
from camomile import Camomile
server = 'http://example.com'
client = Camomile(server)
client.login(username, password)
var server = 'http://example.com';
Camomile.setURL(server);
JSON response upon success
{
"success": "Authentication succeeded."
}
logout
POST /logout
POST /logout HTTP/1.1
client.logout()
JSON response upon success
{
"success": "Logout succeeded."
}
get logged in user
GET /me
user = client.me()
id_user = client.me(returns_id=True)
GET /me HTTP/1.1
Sample JSON response
{
"_id": "555299eff80f910100d741d1",
"description": "",
"role": "user",
"username": "johndoe"
}
update password
PUT /me
client.update_password('new_password')
client.update_password("new_password", callback);
PUT /me HTTP/1.1
{
"password": "new_password"
}
JSON response upon success
{
"success": "Password successfully updated."
}
Users & Groups
create new user
POST /user
DATA PARAMETERS
Key | Type | Description |
---|---|---|
username | String | The user name (required, unique and without space, can’t be updated) |
password | String | The password (required) |
description | free | A description of the user |
role | String | The user role (“admin” or “user”) (required) |
POST /user HTTP/1.1
{'username': 'johndoe',
'password': 'secretpassword',
'description': 'annotator',
'role': 'user'}
user = client.createUser('username', 'password', role='user',
description={'affiliation': 'LIMSI/CNRS',
'status': 'PhD student'})
client.createUser('username', 'password',
{'affiliation': 'LIMSI/CNRS', 'status': 'PhD student'}
'user', callback);
Sample JSON response
{
"_id": "558818da01e0ef01006e979b",
"description": "annotator",
"role": "user",
"username": "johndoe"
}
delete one user
DELETE /user/:id_user
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_user | String | The user identifier (required) |
client.deleteUser(id_user)
DELETE /user/:id_user HTTP/1.1
JSON response upon success
{
"success": "Successfully deleted."
}
get all users
GET /user
DATA PARAMETERS
Key | Type | Description |
---|---|---|
username | String | filter users by username (optional) |
users = client.getUsers()
GET /user HTTP/1.1
Sample JSON response
[
{
"_id": "5552998df80f910100d741d0",
"description": "",
"role": "admin",
"username": "root"
},
{
"_id": "558818da01e0ef01006e979b",
"description": "annotator",
"role": "user",
"username": "johndoe"
}
]
get one user
GET /user/:id_user
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_user | String | The user identifier (required) |
user = client.getUser(id_user)
GET /user/:id_user HTTP/1.1
Sample JSON response
{
"_id": "558818da01e0ef01006e979b",
"description": "annotator",
"role": "user",
"username": "johndoe"
}
update one user
PUT /user/:id_user
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_user | String | The user identifier (required) |
DATA PARAMETERS
Key | Type | Description |
---|---|---|
password | String | The password |
description | free | A description of the user |
role | String | The user role (“admin” or “user”) |
PUT /user/:id_user HTTP/1.1
{'description': 'expert annotator'}
user = client.updateUser(id_user,
password='password',
description={'number': 42},
role='admin')
Sample JSON response
{
"_id": "558818da01e0ef01006e979b",
"description": "expert annotator",
"role": "user",
"username": "johndoe"
}
get one user’s groups
GET /user/:id_user
/group
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_user | String | The user identifier (required) |
GET /user/:id_user/group HTTP/1.1
id_groups = client.getUserGroups(id_user)
Sample JSON response
[
"55881d1601e0ef01006e979c"
]
get all groups
GET /group
DATA PARAMETERS
Key | Type | Description |
---|---|---|
name | String | filter groups by name (optional) |
GET /group HTTP/1.1
{'name': 'project'}
groups = client.getGroups()
Sample JSON response
[
{
"_id": "55881d1601e0ef01006e979c",
"description": "members of the project",
"name": "project",
"users": ["558818da01e0ef01006e979b", "55881d6001e0ef01006e979d"]
}
]
get one group
GET /group/:id_group
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_group | String | The group identifier (required) |
GET /group/:id_group HTTP/1.1
group = client.getGroup(id_group)
Sample JSON response
{
"_id": "55881d1601e0ef01006e979c",
"description": "members of the project",
"name": "project",
"users": ["558818da01e0ef01006e979b", "55881d6001e0ef01006e979d"]
}
create new group
POST /group
DATA PARAMETERS
Key | Type | Description |
---|---|---|
name | String | The group name (can’t be updated) |
description | free | A description of the group |
POST /group HTTP/1.1
{'name': 'guests'}
group = client.createGroup(
'limsi',
description={'affiliation': 'LIMSI'})
Sample JSON response
{
"_id": "55881f8301e0ef01006e979e",
"description": "",
"name": "guests",
"users": []
}
update one group
PUT /group/:id_group
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_group | String | The group identifier (required) |
DATA PARAMETERS
Key | Type | Description |
---|---|---|
description | free | A description of the group |
PUT /group/:id_group HTTP/1.1
{ 'description': 'open trial'}
group = client.updateGroup(
id_group,
description={'affiliation': 'LIMSI/CNRS'})
Sample JSON response
{
"_id": "55881f8301e0ef01006e979e",
"description": "open trial",
"name": "guests",
"users": []
}
delete one group
DELETE /group/:id_group
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_group | String | The group identifier (required) |
DELETE /group/:id_group HTTP/1.1
client.deleteGroup(id_group)
JSON response upon success
{
"success": "Successfully deleted."
}
add one user to one group
PUT /group/:id_group
/user/:id_user
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_group | String | The group identifier (required) |
id_user | String | The user identifier (required) |
PUT /group/:id_group/user/:id_user HTTP/1.1
client.addUserToGroup(id_user, id_group)
Sample JSON response
{
"_id": "55881d1601e0ef01006e979c",
"description": "members of the project",
"name": "project",
"users": ["558818da01e0ef01006e979b", "55881d6001e0ef01006e979d"]
}
remove one user from one group
DELETE /group/:id_group
/user/:id_user
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_group | String | The group identifier (required) |
id_user | String | The user identifier (required) |
client.removeUserFromGroup(id_user, id_group)
DELETE /group/:id_group/user/:id_user HTTP/1.1
Sample JSON response
{
"_id": "55881d1601e0ef01006e979c",
"description": "members of the project",
"name": "project",
"users": ["558818da01e0ef01006e979b"]
}
Corpora
get all READable corpora
GET /corpus
corpora = client.getCorpora()
GET /corpus HTTP/1.1
Sample JSON response
[
{
"_id": "555daefff80f910100d741d6",
"description": "Test corpus",
"name": "ctest"
}
]
get one corpus
GET /corpus/:id_corpus
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_corpus | String | The corpus identifier (required) |
corpus = client.getCorpus(id_corpus)
GET /corpus/:id_corpus HTTP/1.1
Sample JSON response
{
"_id": "555daefff80f910100d741d6",
"description": "Test corpus",
"name": "ctest"
}
create new corpus
POST /corpus
DATA PARAMETERS
Key | Type | Description |
---|---|---|
name | String | The corpus name (unique) |
description | free | A description of the corpus |
corpus = client.createCorpus(
'unique name',
description={'license': 'Creative Commons'})
POST /corpus HTTP/1.1
{'name': 'unique name', 'description': {'license': 'Creative Commons'}}
Sample JSON response
{
"_id": "555daefff80f910100d741d6",
"description": {"license": "Creative Commons"},
"name": "unique name"
}
update one corpus
PUT /corpus/:id_corpus
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_corpus | String | The corpus identifier (required) |
DATA PARAMETERS
Key | Type | Description |
---|---|---|
name | String | The corpus name (unique) |
description | free | A description of the corpus |
corpus = client.updateCorpus(
id_corpus,
name='new name',
description={'license': 'MIT'})
PUT /corpus/:id_corpus HTTP/1.1
{'description': {'license': 'MIT'},
'name': 'new name'}
Sample JSON response
{
"_id": "555daefff80f910100d741d6",
"description": {"license": "MIT"},
"name": "new name"
}
delete one corpus
DELETE /corpus/:id_corpus
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_corpus | String | The corpus identifier (required) |
client.deleteCorpus(id_corpus)
DELETE /corpus/:id_corpus HTTP/1.1
JSON response upon success
{
"success": "Successfully deleted."
}
get one corpus’ permissions
GET /corpus/:id_corpus
/permissions
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_corpus | String | The corpus identifier (required) |
GET /corpus/:id_corpus/permissions HTTP/1.1
permissions = client.getCorpusPermissions(id_corpus)
Sample JSON response
{
"users": [
"5423dc0900e5c11a8fc723ba",
"5423dc0900e5c11a8fc723bb"
],
"groups": [
"5423dfeb00e5c11a8fc723bc",
]
}
give one user permissions to one corpus
PUT /corpus/:id_corpus
/user/:id_user
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_corpus | String | The corpus identifier (required) |
id_user | String | The user identifier (required) |
DATA PARAMETERS
Key | Type | Description |
---|---|---|
right | 1, 2 or 3 | The corpus permissions (1:READ, 2:WRITE, 3:ADMIN) |
client.setCorpusPermissions(id_corpus, client.ADMIN, user=id_user)
PUT /corpus/:id_corpus/user/:id_user HTTP/1.1
{'right': 3}
Sample JSON response
{
"users": {"555299eff80f910100d741d1": 3,
"5552bf5cf80f910100d741d2": 2,
"55881d6001e0ef01006e979d": 3}
}
remove one user’s permissions to one corpus
DELETE /corpus/:id_corpus
/user/:id_user
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_corpus | String | The corpus identifier (required) |
id_user | String | The user identifier (required) |
client.removeCorpusPermissions(id_corpus, user=id_user)
DELETE /corpus/:id_corpus/user/:id_user HTTP/1.1
Sample JSON response
{
"users": {"555299eff80f910100d741d1": 3,
"5552bf5cf80f910100d741d2": 2}
}
give one group permissions to one corpus
PUT /corpus/:id_corpus
/group/:id_group
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_corpus | String | The corpus identifier (required) |
id_group | String | The group identifier (required) |
DATA PARAMETERS
Key | Type | Description |
---|---|---|
right | 1, 2 or 3 | The corpus permissions (1:READ, 2:WRITE, 3:ADMIN) |
client.setCorpusPermissions(id_corpus, ADMIN, group=id_group)
PUT /corpus/:id_corpus/group/:id_group HTTP/1.1
Sample JSON response
{
"groups": {"55881d1601e0ef01006e979c": 2},
"users": {"555299eff80f910100d741d1": 3,
"5552bf5cf80f910100d741d2": 2}
}
remove one group’s permissions to one corpus
DELETE /corpus/:id_corpus
/group/:id_group
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_corpus | String | The corpus identifier (required) |
id_group | String | The group identifier (required) |
client.removeCorpusPermissions(id_corpus, group=id_group)
DELETE /corpus/:id_corpus/group/:id_group HTTP/1.1
Sample JSON response
{
"users": {"555299eff80f910100d741d1": 3,
"5552bf5cf80f910100d741d2": 2}
}
Media
get all media
GET /medium
DATA PARAMETERS
Key | Type | Description |
---|---|---|
name | String | filter media by name |
client.getMedia()
GET /medium HTTP/1.1
Sample JSON response
[
{"_id": "...", "description": "", "id_corpus": "...", "name": "show1", "url": ""},
{"_id": "...", "description": "", "id_corpus": "...", "name": "show2", "url": ""}
...
]
get one medium
GET /medium/:id_medium`
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_medium | String | The medium identifier (required) |
client.getMedium(id_medium)
GET /medium/:id_medium HTTP/1.1
Sample JSON response
{
"_id": "555db2e6f80f910100d741d8",
"description": "",
"id_corpus": "555daefff80f910100d741d6",
"name": "LCP_PileEtFace_2012-11-30_012500",
"url": ""
}
get one corpus’ media
GET /corpus/:id_corpus
/medium
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_corpus | String | The corpus identifier (required) |
DATA PARAMETERS
Key | Type | Description |
---|---|---|
name | String | filter media by name |
client.getMedia(id_corpus)
GET /corpus/:id_corpus/medium HTTP/1.1
Sample JSON response
{
"_id": "555db2e6f80f910100d741d8",
"description": "",
"id_corpus": "555daefff80f910100d741d6",
"name": "LCP_PileEtFace_2012-11-30_012500",
"url": ""
}
create new medium(a) in one corpus
POST /corpus/:id_corpus/medium
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_corpus | String | The corpus identifier (required) |
DATA PARAMETERS
Key | Type | Description |
---|---|---|
name | String | The medium name (unique) |
url | String | absolute or relative URL to the medium |
description | free | A description of the medium |
OR list of {name, url, description}
client.createMedium(id_corpus, name, url, description)
media = [{'name':'show1'}, {'name':'show2'}]
client.createMedia(id_corpus, media)
POST /corpus/:id_corpus/medium HTTP/1.1
{'name': 'LCP_PileEtFace_2012-11-30_012500'}
Sample JSON response
{
"_id": "55895e90c70125010026f6b5",
"id_corpus": "558955cec70125010026f6aa",
"name": "LCP_PileEtFace_2012-11-30_012500",
"url": ""
}
update one medium
PUT /medium/:id_medium
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_medium | String | The medium identifier (required) |
DATA PARAMETERS
Key | Type | Description |
---|---|---|
name | String | The medium name (unique) |
url | String | absolute or relative URL to the medium |
description | free | A description of the medium |
client.updateMedium(id_medium, name, url, description)
PUT /medium/:id_medium HTTP/1.1
{'description': 'LCP channel'}
Sample JSON response
{
"_id": "55895e90c70125010026f6b5",
"id_corpus": "558955cec70125010026f6aa",
"name": "LCP_PileEtFace_2012-11-30_012500",
"url": "",
"description": "LCP channel"
}
delete one medium
DELETE /medium/:id_medium
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_medium | String | The medium identifier (required) |
client.deleteMedium(id_medium)
DELETE /medium/:id_medium HTTP/1.1
JSON response upon success
{
"success": "Successfully deleted."
}
stream one medium in default format
GET /medium/:id_medium/video
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_medium | String | The medium identifier (required) |
client.streamMedium(id_medium)
GET /medium/:id_medium/video HTTP/1.1
stream one medium in WebM, MP4 or OGV
GET /medium/:id_medium/{webm,mp4,ogv}
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_medium | String | The medium identifier (required) |
client.streamMedium(id_medium, format='webm')
client.streamMedium(id_medium, format='mp4')
client.streamMedium(id_medium, format='ogv')
GET /medium/:id_medium/webm HTTP/1.1
GET /medium/:id_medium/mp4 HTTP/1.1
GET /medium/:id_medium/ogv HTTP/1.1
Layers
get all layers
GET /layer
DATA PARAMETERS
Key | Type | Description |
---|---|---|
name | String | filter layers by name (optional) |
fragment_type | String | filter layers by fragment type (optional) |
data_type | String | filter layers by data type (optional) |
GET /layer HTTP/1.1
layers = client.getLayers()
Sample JSON response
{
}
get one layer
GET /layer/:id_layer
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_layer | String | The layer identifier (required) |
GET /layer/:id_layer HTTP/1.1
layer = client.getLayer(id_layer)
Sample JSON response
{
}
get one corpus’ layers
GET /corpus/:id_corpus/layer
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_corpus | String | The corpus identifier (required) |
DATA PARAMETERS
Key | Type | Description |
---|---|---|
name | String | filter layers by name (optional) |
fragment_type | String | filter layers by fragment type (optional) |
data_type | String | filter layers by data type (optional) |
GET /corpus/:id_corpus/layer HTTP/1.1
layer = client.getLayers(id_corpus)
Sample JSON response
{
}
create new layer(s) in one corpus
POST /corpus/:id_corpus/layer
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_corpus | String | The corpus identifier (required) |
DATA PARAMETERS
Key | Type | Description |
---|---|---|
name | String | layer name (required) |
description | free | layer description (optional) |
fragment_type | free | layer fragment type (optional) |
data_type | free | layer data type (optional) |
annotations | list | list of annotations (optional) |
POST /corpus/:id_corpus/layer HTTP/1.1
client.createLayer(id_corpus, name, description, fragment_type, data_type, annotations)
Sample JSON response
{
}
update one layer
PUT /layer/:id_layer
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_layer | String | The layer identifier (required) |
DATA PARAMETERS
Key | Type | Description |
---|---|---|
name | String | layer name (optional) |
description | free | layer description (optional) |
fragment_type | free | layer fragment type (optional) |
data_type | free | layer data type (optional) |
PUT /layer/:id_layer HTTP/1.1
client.updateLayer(id_layer, name, description, fragment_type, data_type)
Sample JSON response
{
}
delete one layer
DELETE /layer/:id_layer
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_layer | String | The layer identifier (required) |
DELETE /layer/:id_layer HTTP/1.1
client.deleteLayer(id_layer)
Sample JSON response
{
}
get one layer’s permissions
GET /layer/:id_layer/permissions
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_layer | String | The layer identifier (required) |
GET /layer/:id_layer/permissions HTTP/1.1
permission = client.getLayerPermissions(id_layer)
Sample JSON response
{
}
give one user permissions to one layer
PUT /layer/:id_layer/user/:id_user
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_layer | String | The layer identifier (required) |
id_user | String | The user identifier (required) |
DATA PARAMETERS
Key | Type | Description |
---|---|---|
right | 1, 2 or 3 | The layer permissions (1:READ, 2:WRITE, 3:ADMIN) |
PUT /layer/:id_layer/user/:id_user HTTP/1.1
client.setLayerPermissions(id_layer, permission, user=id_user)
Sample JSON response
{
}
remove one user’s permissions to one layer
DELETE /layer/:id_layer/user/:id_user
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_layer | String | The layer identifier (required) |
id_user | String | The user identifier (required) |
DELETE /layer/:id_layer/user/:id_user HTTP/1.1
client.removeLayerPermissions(id_layer, permission, user=id_user)
Sample JSON response
{
}
give one group permissions to one layer
PUT /layer/:id_layer/group/:id_group
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_layer | String | The layer identifier (required) |
id_group | String | The group identifier (required) |
DATA PARAMETERS
Key | Type | Description |
---|---|---|
right | 1, 2 or 3 | The layer permissions (1:READ, 2:WRITE, 3:ADMIN) |
PUT /layer/:id_layer/group/:id_group HTTP/1.1
client.setLayerPermissions(id_layer, permission, group=id_group)
Sample JSON response
{
}
remove on group’s permissions to one layer
DELETE /layer/:id_layer/group/:id_group
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_layer | String | The layer identifier (required) |
id_group | String | The group identifier (required) |
DELETE /layer/:id_layer/group/:id_group HTTP/1.1
client.removeLayerPermissions(id_layer, permission, group=id_group)
Sample JSON response
{
}
Annotations
get all annotations
GET /annotation
DATA PARAMETERS
Key | Type | Description |
---|---|---|
id_medium | String | filter annotations by medium (optional) |
fragment | String | filter annotations by fragment (optional) |
data | String | filter annotations by data (optional) |
GET /annotation HTTP/1.1
client.getAnnotations(medium=id_medium, fragment=fragment, data=data)
Sample JSON response
{
}
get one annotation
GET /annotation/:id_annotation
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_annotation | String | The annotation identifier (required) |
GET /annotation/:id_annotation HTTP/1.1
client.getAnnotation(id_annotation)
Sample JSON response
{
}
get one layer’s annotations
GET /layer/:id_layer/annotation
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_layer | String | The layer identifier (required) |
DATA PARAMETERS
Key | Type | Description |
---|---|---|
id_medium | String | filter annotations by medium (optional) |
fragment | String | filter annotations by fragment (optional) |
data | String | filter annotations by data (optional) |
GET /layer/:id_layer/annotation HTTP/1.1
client.getAnnotations(id_layer, medium=id_medium, fragment=fragment, data=data)
Sample JSON response
{
}
create new annotation(s) in one layer
POST /layer/:id_layer/annotation
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_layer | String | The layer identifier (required) |
DATA PARAMETERS
Key | Type | Description |
---|---|---|
id_medium | String | medium identifier (required) |
fragment | free | annotation fragment (required) |
data | free | annotation data (required) |
OR
list of {id_medium:…, fragment:…, data:…}
POST /layer/:id_layer/annotation HTTP/1.1
client.createAnnotation(id_layer, medium=id_medium, fragment=fragment, data=data)
OR
client.createAnnotations(id_layer,annotations)
Sample JSON response
{
}
update one annotation
PUT /annotation/:id_annotation
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_annotation | String | The annotation identifier (required) |
DATA PARAMETERS
Key | Type | Description |
---|---|---|
fragment | free | annotation fragment (optional) |
data | free | annotation data (optional) |
PUT /annotation/:id_annotation HTTP/1.1
client.updateAnnotation(id_annotation, fragment=fragment, data=data)
Sample JSON response
{
}
delete one annotation
DELETE /annotation/:id_annotation
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_annotation | String | The annotation identifier (required) |
DELETE /annotation/:id_annotation HTTP/1.1
client.deleteAnnotation(id_annotation)
Sample JSON response
{
}
Queues
get all queues
GET /queue
DATA PARAMETERS
Key | Type | Description |
---|---|---|
name | String | queue name (optional) |
GET /queue HTTP/1.1
queues = client.getQueues()
Sample JSON response
[
{
"_id": "5423dc0900e5c11a8fc723bb",
"name": "name",
"description": {"my": "description"},
"list": ["item1", "item2"]
},
...
]
get one queue
GET /queue/:id_queue
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_queue | String | The queue identifier (required) |
GET /queue/:id_queue HTTP/1.1
queues = client.getQueue(id_queue)
Sample JSON response
{
"_id": "5423dc0900e5c11a8fc723bb",
"name": "name",
"description": {"my": "description"},
"list": ["item1", "item2"]
}
create new queue
POST /queue
DATA PARAMETERS
Key | Type | Description |
---|---|---|
name | String | queue name (required) |
description | free | queue description (optional) |
POST /queue HTTP/1.1
queue = client.createQueue('queue name', description={'my': 'description'})
Sample JSON request
{
"name": "name",
"description": {"my": "description"}
}
Sample JSON response
{
"_id": "5423dc0900e5c11a8fc723bb",
"name": "name",
"description": {"my": "description"},
"list": []
}
update one queue
PUT /queue/:id_queue
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_queue | String | The queue identifier (required) |
DATA PARAMETERS
Key | Type | Description |
---|---|---|
name | String | queue name (optional) |
description | free | queue description (optional) |
list | list | list of new queue elements (optional) |
PUT /queue/:id_queue HTTP/1.1
queue = client.updateQueue(id_queue,
name='new name', description={'new': 'description'},
elements=['item1', 'item2'])
Sample JSON request
{
"name": "new name",
"description": {"new": "description"},
"list": ["item1", "item2"]
}
Sample JSON response
{
"_id":"5423dc0900e5c11a8fc723bb",
"name": "new name",
"description": {"new": "description"},
"list": ["item1", "item2"]
}
append item(s) to one queue
PUT /queue/:id_queue/next
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_queue | String | The queue identifier (required) |
DATA PARAMETERS
Type | Description |
---|---|
list | list of queue elements |
PUT /queue/:id_queue/next HTTP/1.1
queue = client.enqueue(id_queue, items)
Sample JSON response
{
}
pop one item from one queue
GET /queue/:id_queue/next
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_queue | String | The queue identifier (required) |
GET /queue/:id_queue/next HTTP/1.1
item = client.dequeue(id_queue)
get next item on one queue (without actually removing it)
(Non-destructively) pick first element of queue
GET /queue/:id_queue/first
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_queue | String | The queue identifier (required) |
GET /queue/:id_queue/first HTTP/1.1
item = client.pick(id_queue)
get number of items in one queue
(Non-destructively) get number of elements in queue
GET /queue/:id_queue/length
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_queue | String | The queue identifier (required) |
GET /queue/:id_queue/length HTTP/1.1
item = client.pickLength(id_queue)
get all items from one queue
(Non-destructively) pick all elements of queue
GET /queue/:id_queue/all
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_queue | String | The queue identifier (required) |
GET /queue/:id_queue/all HTTP/1.1
item = client.pickAll(id_queue)
remove one queue
DELETE /queue/:id_queue
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_queue | String | The queue identifier (required) |
DELETE /queue/:id_queue HTTP/1.1
client.deleteQueue(id_corpus)
Sample JSON response
{
"success": "Successfully deleted."
}
get one queue’s permissions
GET /queue/:id_queue/permissions
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_queue | String | The queue identifier (required) |
GET /queue/:id_queue/permissions HTTP/1.1
client.getQueuePermissions(id_queue)
Sample JSON response
{
}
give one user permissions to one queue
PUT /queue/:id_queue/user/:id_user
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_queue | String | The queue identifier (required) |
id_user | String | The user identifier (required) |
DATA PARAMETERS
Key | Type | Description |
---|---|---|
right | 1, 2 or 3 | The queue permissions (1:READ, 2:WRITE, 3:ADMIN) |
PUT /queue/:id_queue/user/:id_user HTTP/1.1
client.setQueuePermissions(id_queue, client.WRITE, user=id_user)
Sample JSON response
{
}
remove one user’s permissions to one queue
DELETE /queue/:id_queue/user/:id_user
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_queue | String | The queue identifier (required) |
id_user | String | The user identifier (required) |
DELETE /queue/:id_queue/user/:id_user HTTP/1.1
client.removeQueuePermissions(id_queue, user=id_user)
Sample JSON response
{
}
give one group permissions to one queue
PUT /queue/:id_queue/group/:id_group
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_queue | String | The queue identifier (required) |
id_group | String | The group identifier (required) |
DATA PARAMETERS
Key | Type | Description |
---|---|---|
right | 1, 2 or 3 | The queue permissions (1:READ, 2:WRITE, 3:ADMIN) |
PUT /queue/:id_queue/group/:id_group HTTP/1.1
client.setQueuePermissions(id_queue, client.WRITE, group=id_group)
Sample JSON response
{
}
remove on group’s permissions to one queue
DELETE /queue/:id_queue/group/:id_group
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
id_queue | String | The queue identifier (required) |
id_group | String | The group identifier (required) |
DELETE /queue/:id_queue/group/:id_group HTTP/1.1
client.removeQueuePermissions(id_queue, group=id_group)
Sample JSON response
{
}
Metadata
Metadata is only available for Corpus
, Layer
and Medium
get
GET /:resource_type/:resource_id/metadata/:path
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
resource_type | String | The resource type (corpus, layer or medium) (required) |
resource_id | String | The resource identifier (required) |
path | String | The metadata path, if not set return first level keys (optional) |
DATA PARAMETERS FOR FILE
Parameter | Type | Description |
---|---|---|
type | String | set to file |
filename | String | filename |
data | String | Base64 encoded file content (Only set if last level and not ?file parameter) |
client.getCorpusMetadata(
'555daefff80f910100d741d6',
'level1')
GET /corpus/555daefff80f910100d741d6/metadata/level1 HTTP/1.1
# Or for download file
GET /corpus/555daefff80f910100d741d6/metadata/my.picture?file HTTP/1.1
Camomile.getCorpusMetadata('555daefff80f910100d741d6', 'test2.child', function(err, datas) {
console.log(datas);
});
Sample JSON response
{
"mykey": "value",
"myarray": ["value1", "value2"],
"myobject": {"mykey": "myvalue"}
}
File “`json { "myfile”: { “filename”: “myvalue”, “type”: “file”
} } “`
get first level keys
GET /:resource_type/:resource_id/metadata/:path*.*
End path with .
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
resource_type | String | The resource type (corpus, layer or medium) (required) |
resource_id | String | The resource identifier (required) |
path | String | The metadata path, if not set return first level keys (optional) |
client.getCorpusMetadataKeys(
'555daefff80f910100d741d6',
'level1')
Camomile.getCorpusMetadataKeys('555daefff80f910100d741d6', function(err, datas) {
console.log(datas);
});
Camomile.getCorpusMetadataKeys('555daefff80f910100d741d6', 'level1', function(err, datas) {
console.log(datas);
});
GET /corpus/555daefff80f910100d741d6/metadata/level1. HTTP/1.1
Sample JSON response
[
"mykey"
"myarray"
"myobject"
]
create / update
POST /:resource_type/:resource_id/metadata/
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
resource_type | String | The resource type (corpus, layer or medium) (required) |
resource_id | String | The resource identifier (required) |
client.setCorpusMetadata(
'555daefff80f910100d741d6',
{'name': 'my metadata', 'level1': {'my_array': ['value1', 'value2']}})
#OR
client.setCorpusMetadata(
'555daefff80f910100d741d6',
datas="myvalue",
path="my.key")
POST /corpus/555daefff80f910100d741d6/metadata/ HTTP/1.1
{"name": "my metadata", "level1": {"my_array": ["value1", "value2"]}}
Camomile.setCorpusMetadata(
'555daefff80f910100d741d6',
{'name': 'my metadata', 'level1': {'my_array': ['value1', 'value2']}} ,
function(err, success) {
console.log(success);
}
);
Sample JSON response
{
"success": "Successfully created."
}
create / update file
POST /:resource_type/:resource_id/metadata/
Send base64 encoded file
QUERY PARAMETERS
Parameter | Type | Description |
---|---|---|
resource_type | String | The resource type (corpus, layer or medium) (required) |
resource_id | String | The resource identifier (required) |
DATA PARAMETERS
Parameter | Type | Description |
---|---|---|
type | String | set to file (required) |
filename | String | filename (required) |
data | String | Base64 encoded file content (required) |
client.sendCorpusMetadataFile(
'555daefff80f910100d741d6',
'level1.mypicture',
'/path/to/file.ext')
var inputFile = document.getElementById('file');
var file = inputFile.files[0];
Camomile.sendCorpusMetadataFile(
'555daefff80f910100d741d6',
'level1.mypicture',
file,
function(err, success) {
console.log(success);
}
);
POST /corpus/555daefff80f910100d741d6/metadata/ HTTP/1.1
{'level1': {'mypicture': {'type': 'file', 'filename': 'file.ext', 'data': '<base64_encoded_file>'}}}
Sample JSON response
{
"success": "Successfully created."
}
delete
DELETE /corpus/555daefff80f910100d741d6/metadata/:path
Parameter | Type | Description |
---|---|---|
resource_type | String | The resource type (corpus, layer or medium) (required) |
resource_id | String | The resource identifier (required) |
path | String | The metadata path (required) |
client.deleteCorpusMetadata(
'555daefff80f910100d741d6',
'level1')
DELETE /corpus/555daefff80f910100d741d6/metadata/level1 HTTP/1.1
Camomile.deleteCorpusMetadata('555daefff80f910100d741d6', 'level1', function(err, success) {
console.log(success);
});
Sample JSON response
{
"success": "Successfully deleted."
}
Server Sent Event
Server Sent Event is only available for Corpus
, Layer
, Medium
and Queue
Available events
Corpus
- Add and Remove medium
{'corpus': {:corpus}, 'event': {'add_medium': {:medium}}}
- Add and Remove layer
{'corpus': {:corpus}, 'event': {'add_layer': {:layer}}}
- Update corpus attributes
{'corpus': {:corpus}, 'event': {'update': ['description', 'name']}}}
Layer
- Add and Remove annotation
{'layer': {:layer}, 'event': {'add_annotation': {:annotation}}}
- Update layer attributes
{'layer': {:layer}, 'event': {'update': ['name']}}}
Medium
- Update medium attributes
{'medium': {:medium}, 'event': {'update': ['url']}}}
Queue
- Push item in queue
{'queue': {:queue}, 'event': {'push_item': <new_number_of_items_in_queue>}}
- Pop item in queue
{'queue': {:queue}, 'event': {'pop_item': <new_number_of_items_in_queue>}}
get an available channel
POST /listen
POST /listen HTTP/1.1
Sample JSON response
{
"channel_id": 10
}
Connect to SSE entrypoint
GET /listen/:channel_id
Parameter | Type | Description |
---|---|---|
channel_id | Integer | Channel identifier (required) |
Watch resource
PUT /listen/:channel_id/:resource_type/:resource_id
def callback(event):
print event
client.watchCorpus('555daefff80f910100d741d6', callback)
Camomile.listen(function(error, channel_id, event) {
var unwatchCorpus = event.watchCorpus('555daefff80f910100d741d6', function(error, data) {
console.log(data);
// For unwatch corpus:
unwatchCorpus();
});
});
PUT /listen/5/medium/555daefff80f910100d741d6 HTTP/1.1
Sample JSON response
{
"event": "medium:555daefff80f910100d741d6"
}
Unwatch resource
DELETE /listen/:channel_id/:resource_type/:resource_id
client.unwatchCorpus('555daefff80f910100d741d6')
DELETE /listen/5/medium/555daefff80f910100d741d6 HTTP/1.1
Sample JSON response
{
"success": "Successfully unwatched."
}
Miscellaneous
get current date/time
GET /date
GET /date HTTP/1.1
Sample JSON response
{
}
client.date()