Skip to content

Table of contents

Data System

Typing

The notion of document type does not exist in Couchdb.

Cozy-stack introduce this notion through a special _type field.

This type name cannot contain /, and it should be unique among all developers, it is recommended to use the Java naming convention with a domain you own.

All CozyCloud types will be prefixed by io.cozy and be pluralized. Example: /data/io.cozy.events/6494e0ac-dfcb-11e5-88c1-472e84a9cbee Where, io.cozy. is the developer specific prefix, events the actual type, and 6494e0ac-dfcb-11e5-88c1-472e84a9cbee the document’s unique id .

Access a document

Request

GET /data/:type/:id HTTP/1.1
GET /data/io.cozy.events/6494e0ac-dfcb-11e5-88c1-472e84a9cbee HTTP/1.1

Response OK

HTTP/1.1 200 OK
Date: Mon, 27 Sept 2016 12:28:53 GMT
Content-Length: ...
Content-Type: application/json
Etag: "3-6494e0ac6494e0ac"
{
    "_id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee",
    "_type": "io.cozy.events",
    "_rev": "3-6494e0ac6494e0ac",
    "startdate": "20160823T150000Z",
    "enddate": "20160923T160000Z",
    "summary": "A long month",
    "description": "I could go on and on and on ...."
}

Response Error

HTTP/1.1 404 Not Found
Content-Length: ...
Content-Type: application/json
{
    "status": 404,
    "error": "not_found",
    "reason": "deleted",
    "title": "Event deleted",
    "details": "Event 6494e0ac-dfcb-11e5-88c1-472e84a9cbee was deleted",
    "links": { "about": "https://cozy.github.io/cozy-stack/errors.md#deleted" }
}

Possible errors

  • 401 unauthorized (no authentication has been provided)
  • 403 forbidden (the authentication does not provide permissions for this action)
  • 404 not_found
    • reason: missing
    • reason: deleted
  • 500 internal server error

Access multiple documents at once

Request

POST /data/:type/_all_docs HTTP/1.1
POST /data/io.cozy.files/_all_docs?include_docs=true HTTP/1.1
Content-Length: ...
Content-Type: application/json
Accept: application/json
{
    "keys": [
        "7f46ed4ed2a775494da3b0b44e00314f",
        "7f46ed4ed2a775494da3b0b44e003b18"
    ]
}

Response OK

HTTP/1.1 200 OK
Date: Mon, 27 Sept 2016 12:28:53 GMT
Content-Length: ...
Content-Type: application/json
Etag: "3-6494e0ac6494e0ac"
{
    "total_rows": 11,
    "rows": [
        {
            "id": "7f46ed4ed2a775494da3b0b44e00314f",
            "key": "7f46ed4ed2a775494da3b0b44e00314f",
            "value": {
                "rev": "1-870e58f8a1b2130c3a41e767f9c7d93a"
            },
            "doc": {
                "_id": "7f46ed4ed2a775494da3b0b44e00314f",
                "_rev": "1-870e58f8a1b2130c3a41e767f9c7d93a",
                "type": "directory",
                "name": "Uploaded from Cozy Photos",
                "dir_id": "7f46ed4ed2a775494da3b0b44e0027df",
                "created_at": "2017-07-04T06:49:12.844631837Z",
                "updated_at": "2017-07-04T06:49:12.844631837Z",
                "tags": [],
                "path": "/Photos/Uploaded from Cozy Photos"
            }
        },
        {
            "key": "7f46ed4ed2a775494da3b0b44e003b18",
            "error": "not_found"
        }
    ]
}

possible errors

  • 401 unauthorized (no authentication has been provided)
  • 403 forbidden (the authentication does not provide permissions for this action)
  • 500 internal server error

Details

When some keys don’t match an existing document, the response still has a status 200 and the errors are included in the rows field (see above, same behavior as CouchDB).

Create a document

Request

POST /data/:type/ HTTP/1.1
POST /data/io.cozy.events/ HTTP/1.1
Content-Length: ...
Content-Type: application/json
Accept: application/json
{
    "startdate": "20160712T150000",
    "enddate": "20160712T150000"
}

Response OK

HTTP/1.1 201 Created
Content-Length: ...
Content-Type: application/json
{
    "id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee",
    "type": "io.cozy.events",
    "ok": true,
    "rev": "1-6494e0ac6494e0ac",
    "data": {
        "_id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee",
        "_type": "io.cozy.events",
        "_rev": "1-6494e0ac6494e0ac",
        "startdate": "20160712T150000",
        "enddate": "20160712T150000"
    }
}

possible errors

  • 400 bad request
  • 401 unauthorized (no authentication has been provided)
  • 403 forbidden (the authentication does not provide permissions for this action)
  • 500 internal server error

Details

  • A doc cannot contain an _id field, if so an error 400 is returned
  • A doc cannot contain any field starting with _, those are reserved for future cozy & couchdb api evolution

Update an existing document

Request

PUT /data/:type/:id HTTP/1.1
PUT /data/io.cozy.events/6494e0ac-dfcb-11e5-88c1-472e84a9cbee HTTP/1.1
Content-Length: ...
Content-Type: application/json
Accept: application/json
{
    "_id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee",
    "_type": "io.cozy.events",
    "_rev": "1-6494e0ac6494e0ac",
    "startdate": "20160712T150000",
    "enddate": "20160712T200000"
}

Response OK

HTTP/1.1 200 OK
Content-Length: ...
Content-Type: application/json
{
    "id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee",
    "type": "io.cozy.events",
    "ok": true,
    "rev": "2-056f5f44046ecafc08a2bc2b9c229e20",
    "data": {
        "_id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee",
        "_type": "io.cozy.events",
        "_rev": "2-056f5f44046ecafc08a2bc2b9c229e20",
        "startdate": "20160712T150000",
        "enddate": "20160712T200000"
    }
}

Possible errors

  • 400 bad request
  • 401 unauthorized (no authentication has been provided)
  • 403 forbidden (the authentication does not provide permissions for this action)
  • 404 not_found
    • reason: missing
    • reason: deleted
  • 409 Conflict (see Conflict prevention section below)
  • 500 internal server error

Conflict prevention

The client MUST give a _rev field in the document. If this field is different from the one in the current version of the document, an error 409 Conflict will be returned.

Details

  • If no id is provided in URL, an error 400 is returned
  • If the id provided in URL is not the same than the one in document, an error 400 is returned.

Create a document with a fixed id

Request

PUT /data/:type/:id HTTP/1.1
PUT /data/io.cozy.events/6494e0ac-dfcb-11e5-88c1-472e84a9cbee HTTP/1.1
Content-Length: ...
Content-Type: application/json
Accept: application/json
{
    "startdate": "20160712T150000",
    "enddate": "20160712T200000"
}

Response OK

HTTP/1.1 200 OK
Content-Length: ...
Content-Type: application/json
{
    "id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee",
    "type": "io.cozy.events",
    "ok": true,
    "rev": "1-056f5f44046ecafc08a2bc2b9c229e20",
    "data": {
        "_id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee",
        "_type": "io.cozy.events",
        "_rev": "1-056f5f44046ecafc08a2bc2b9c229e20",
        "startdate": "20160712T150000",
        "enddate": "20160712T200000"
    }
}

Possible errors

  • 400 bad request
  • 401 unauthorized (no authentication has been provided)
  • 403 forbidden (the authentication does not provide permissions for this action)
  • 404 not_found
    • reason: missing
    • reason: deleted
  • 409 Conflict (see Conflict prevention section below)
  • 500 internal server error

Details

  • No id should be provide in the document itself

Delete a document

Request

DELETE /data/:type/:id?rev=:rev HTTP/1.1
DELETE /data/io.cozy.events/6494e0ac-dfcb-11e5-88c1-472e84a9cbee?rev=1-82a7144c9ec228c9a851b8a1c1aa225b HTTP/1.1
Accept: application/json

Response OK

HTTP/1.1 200 OK
Content-Length: ...
Content-Type: application/json
{
    "id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee",
    "type": "io.cozy.events",
    "ok": true,
    "rev": "2-056f5f44046ecafc08a2bc2b9c229e20",
    "_deleted": true
}

Possible errors

  • 400 bad request
  • 401 unauthorized (no authentication has been provided)
  • 403 forbidden (the authentication does not provide permissions for this action)
  • 404 not_found
    • reason: missing
    • reason: deleted
  • 409 Conflict (see Conflict prevention section below)
  • 500 internal server error

Conflict prevention

It is possible to use either a rev query string parameter or a HTTP If-Match header to prevent conflict on deletion:

  • If none is passed or they are different, an error 400 is returned
  • If only one is passed or they are equals, the document will only be deleted if its _rev match the passed one. Otherwise, an error 409 is returned.

Details

  • If no id is provided in URL, an error 400 is returned

We have added a non-standard _normal_docs endpoint since _all_docs endpoint sends the design docs in the response and that it makes it hard to use pagination on it.

This _normal_docs endpoint skip the design docs (and does not count them in thetotal_rows). It accepts three parameters in the query string: limit (default: 100), skip (default: 0), and bookmark (default: ‘’).

The response format looks like a _find response with mango. And, like for _find, the limit cannot be more than 1000. The pagination is also the same: both bookmark and skip can be used, but bookmark is recommended for performances.

Request

GET /data/io.cozy.events/_normal_docs?limit=100&bookmark=g1AAAAB2eJzLYWBgYMpgSmHgKy5JLCrJTq2MT8lPzkzJBYorGKQYpVqaJRoZm1paWFiapFkamhknGpilJiampZkYJRmC9HHA9OUAdTASpS0rCwAlah76 HTTP/1.1
Accept: application/json

Response

HTTP/1.1 200 OK
Content-Type: application/json
{
    "rows": [
        {
            "_id": "16e458537602f5ef2a710089dffd9453",
            "_rev": "1-967a00dff5e02add41819138abb3284d",
            "field": "value"
        },
        {
            "_id": "f4ca7773ddea715afebc4b4b15d4f0b3",
            "_rev": "2-7051cbe5c8faecd085a3fa619e6e6337",
            "field": "other-value"
        },
        ...
    ],
    "total_rows": 202,
    "bookmark": "g1AAAAB2eJzLYWBgYMpgSmHgKy5JLCrJTq2MT8lPzkzJBYorGKQYpVqaJRoZm1paWFiapFkamhknGpilJiampZkYJRmC9HHA9OUAdTASpS0rCwAlah76"
}

List all the documents (alternative & not pagginated way)

You can use _all_docs endpoint to get the list of all the documents. In some cases the use of this route is legitimate, but we recommend to avoid it as much as possible.

The stack also supports a Fields query parameter to only include those fields in the response (with an uppercase F to avoid collusion with a possible future fields by CouchDB), and a DesignDocs query parameter to skip design docs. Example: ?Fields=name,metadata.title,tags&DesignDocs=false.

Request

GET /data/io.cozy.events/_all_docs?include_docs=true HTTP/1.1
Accept: application/json

Response

HTTP/1.1 200 OK
Content-Type: application/json
{
    "offset": 0,
    "rows": [
        {
            "id": "16e458537602f5ef2a710089dffd9453",
            "key": "16e458537602f5ef2a710089dffd9453",
            "value": {
                "rev": "1-967a00dff5e02add41819138abb3284d"
            },
            "doc": {
                "field": "value"
            }
        },
        {
            "id": "f4ca7773ddea715afebc4b4b15d4f0b3",
            "key": "f4ca7773ddea715afebc4b4b15d4f0b3",
            "value": {
                "rev": "2-7051cbe5c8faecd085a3fa619e6e6337"
            },
            "doc": {
                "field": "other-value"
            }
        }
    ],
    "total_rows": 2
}

Details

See _all_docs in couchdb docs

List the known doctypes

A permission on io.cozy.doctypes for GET is needed to query this endoint.

Request

GET /data/_all_doctypes HTTP/1.1
Accept: application/json

Response

HTTP/1.1 200 OK
Content-Type: application/json
["io.cozy.files", "io.cozy.jobs", "io.cozy.triggers", "io.cozy.settings"]

Others

  • The creation and usage of Mango indexes is possible.
  • CouchDB behaviors are not always straight forward: see some quirks for more details.

Access a design document

A design document is a special CouchDB document that represents a view or Mango index definition.

Request

GET /data/:type/_design/:ddoc HTTP/1.1
GET /data/io.cozy.events/_design/c4a8fa4a4660b8eed43137881500265c HTTP/1.1

Response OK

HTTP/1.1 200 OK
Content-Type: application/json
{
  "_id": "_design/c4a8fa4a4660b8eed43137881500265c",
  "_rev": "1-56cf55098fc69450f84a22a632ffafb9",
  "language": "query",
  "views": {
    "by-startdate-and-enddate": {
      "map": {
        "fields": {
          "startdate": "asc",
          "enddate": "asc",
        },
        "partial_filter_selector": {}
      },
      "reduce": "_count",
      "options": {
        "def": {
          "fields": [
            "startdate",
            "enddate",
            "metadata.datetime"
          ]
        }
      }
    }
  }
}

Access all design documents for a doctype

Request

GET /data/:type/_design_docs HTTP/1.1
GET /data/io.cozy.events/_design_docs HTTP/1.1

Response OK

HTTP/1.1 200 OK
Content-Type: application/json
{
  "total_rows": 123,
  "offset": 57,
  "rows": [
      ...
  ]
}

Delete a design document

Request

DELETE /data/:type/_design/:ddoc HTTP/1.1
DELETE /data/io.cozy.events/_design/c4a8fa4a4660b8eed43137881500265c?rev=1-1aa097a2eef904db9b1842342e6c6f50 HTTP/1.1

Response OK

HTTP/1.1 200 OK
Content-Type: application/json
{
  "ok": true,
  "id": "_design/c4a8fa4a4660b8eed43137881500265c",
  "rev": "2-2ad11c9dc32df12a4b24f994807408ba"
}

Copy a design document

This is useful to duplicate a view or Mango index definition, without having to recompute the whole B-Tree. The original and the copy will both use the same index on disk.

Request

POST /data/:type/_design/:ddoc/copy HTTP/1.1
POST /data/io.cozy.events/_design/c4a8fa4a4660b8eed43137881500265c/copy?rev=1-1aa097a2eef904db9b1842342e6c6f50 HTTP/1.1
Destination: _design/d7349ab71c0859c408a725ebbfd453b18aa94ec7

Response OK

HTTP/1.1 201 Created
Content-Type: application/json
{
  "ok": true,
  "id": "_design/d7349ab71c0859c408a725ebbfd453b18aa94ec7",
  "rev": "1-1aa097a2eef904db9b1842342e6c6f50"
}

Delete a database

Request

DELETE /data/:type/ HTTP/1.1
DELETE /data/io.cozy.events/ HTTP/1.1

Response OK

HTTP/1.1 200 OK
Content-Type: application/json
{
  "ok": true,
  "deleted": true
}