[Table of contents](README.md#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 ```http GET /data/:type/:id HTTP/1.1 ``` ```http GET /data/io.cozy.events/6494e0ac-dfcb-11e5-88c1-472e84a9cbee HTTP/1.1 ``` ### Response OK ```http HTTP/1.1 200 OK Date: Mon, 27 Sept 2016 12:28:53 GMT Content-Length: ... Content-Type: application/json Etag: "3-6494e0ac6494e0ac" ``` ```json { "_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 HTTP/1.1 404 Not Found Content-Length: ... Content-Type: application/json ``` ```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 ```http POST /data/:type/_all_docs HTTP/1.1 ``` ```http POST /data/io.cozy.files/_all_docs?include_docs=true HTTP/1.1 Content-Length: ... Content-Type: application/json Accept: application/json ``` ```json { "keys": [ "7f46ed4ed2a775494da3b0b44e00314f", "7f46ed4ed2a775494da3b0b44e003b18" ] } ``` ### Response OK ```http HTTP/1.1 200 OK Date: Mon, 27 Sept 2016 12:28:53 GMT Content-Length: ... Content-Type: application/json Etag: "3-6494e0ac6494e0ac" ``` ```json { "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](http://docs.couchdb.org/en/stable/api/database/bulk-api.html#post--db-_all_docs)). ## Create a document ### Request ```http POST /data/:type/ HTTP/1.1 ``` ```http POST /data/io.cozy.events/ HTTP/1.1 Content-Length: ... Content-Type: application/json Accept: application/json ``` ```json { "startdate": "20160712T150000", "enddate": "20160712T150000" } ``` ### Response OK ```http HTTP/1.1 201 Created Content-Length: ... Content-Type: application/json ``` ```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 ```http PUT /data/:type/:id HTTP/1.1 ``` ```http PUT /data/io.cozy.events/6494e0ac-dfcb-11e5-88c1-472e84a9cbee HTTP/1.1 Content-Length: ... Content-Type: application/json Accept: application/json ``` ```json { "_id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee", "_type": "io.cozy.events", "_rev": "1-6494e0ac6494e0ac", "startdate": "20160712T150000", "enddate": "20160712T200000" } ``` ### Response OK ```http HTTP/1.1 200 OK Content-Length: ... Content-Type: application/json ``` ```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 ```http PUT /data/:type/:id HTTP/1.1 ``` ```http PUT /data/io.cozy.events/6494e0ac-dfcb-11e5-88c1-472e84a9cbee HTTP/1.1 Content-Length: ... Content-Type: application/json Accept: application/json ``` ```json { "startdate": "20160712T150000", "enddate": "20160712T200000" } ``` ### Response OK ```http HTTP/1.1 200 OK Content-Length: ... Content-Type: application/json ``` ```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 ```http DELETE /data/:type/:id?rev=:rev HTTP/1.1 ``` ```http DELETE /data/io.cozy.events/6494e0ac-dfcb-11e5-88c1-472e84a9cbee?rev=1-82a7144c9ec228c9a851b8a1c1aa225b HTTP/1.1 Accept: application/json ``` ### Response OK ```http HTTP/1.1 200 OK Content-Length: ... Content-Type: application/json ``` ```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 ## List all the documents (recommended & paginated way) 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 the`total_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](https://github.com/cozy/cozy-stack/blob/master/docs/mango.md#pagination-cookbook) is also the same: both `bookmark` and `skip` can be used, but `bookmark` is recommended for performances. ### Request ```http GET /data/io.cozy.events/_normal_docs?limit=100&bookmark=g1AAAAB2eJzLYWBgYMpgSmHgKy5JLCrJTq2MT8lPzkzJBYorGKQYpVqaJRoZm1paWFiapFkamhknGpilJiampZkYJRmC9HHA9OUAdTASpS0rCwAlah76 HTTP/1.1 Accept: application/json ``` ### Response ```http HTTP/1.1 200 OK Content-Type: application/json ``` ```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 ```http GET /data/io.cozy.events/_all_docs?include_docs=true HTTP/1.1 Accept: application/json ``` ### Response ```http HTTP/1.1 200 OK Content-Type: application/json ``` ```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](http://docs.couchdb.org/en/stable/api/database/bulk-api.html#db-all-docs) ## List the known doctypes A permission on `io.cozy.doctypes` for `GET` is needed to query this endoint. ### Request ```http GET /data/_all_doctypes HTTP/1.1 Accept: application/json ``` ### Response ```http HTTP/1.1 200 OK Content-Type: application/json ``` ```json ["io.cozy.files", "io.cozy.jobs", "io.cozy.triggers", "io.cozy.settings"] ``` ## Others - The creation and usage of [Mango indexes](mango.md) is possible. - CouchDB behaviors are not always straight forward: see [some quirks](couchdb-quirks.md) for more details. ## Access a design document A design document is a special CouchDB document that represents a view or Mango index definition. ### Request ```http GET /data/:type/_design/:ddoc HTTP/1.1 ``` ```http GET /data/io.cozy.events/_design/c4a8fa4a4660b8eed43137881500265c HTTP/1.1 ``` ### Response OK ```http HTTP/1.1 200 OK Content-Type: application/json ``` ```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 ```http GET /data/:type/_design_docs HTTP/1.1 ``` ```http GET /data/io.cozy.events/_design_docs HTTP/1.1 ``` ### Response OK ```http HTTP/1.1 200 OK Content-Type: application/json ``` ```json { "total_rows": 123, "offset": 57, "rows": [ ... ] } ``` ## Delete a design document ### Request ```http DELETE /data/:type/_design/:ddoc HTTP/1.1 ``` ```http DELETE /data/io.cozy.events/_design/c4a8fa4a4660b8eed43137881500265c?rev=1-1aa097a2eef904db9b1842342e6c6f50 HTTP/1.1 ``` ### Response OK ```http HTTP/1.1 200 OK Content-Type: application/json ``` ```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 ```http POST /data/:type/_design/:ddoc/copy HTTP/1.1 ``` ```http POST /data/io.cozy.events/_design/c4a8fa4a4660b8eed43137881500265c/copy?rev=1-1aa097a2eef904db9b1842342e6c6f50 HTTP/1.1 Destination: _design/d7349ab71c0859c408a725ebbfd453b18aa94ec7 ``` ### Response OK ```http HTTP/1.1 201 Created Content-Type: application/json ``` ```json { "ok": true, "id": "_design/d7349ab71c0859c408a725ebbfd453b18aa94ec7", "rev": "1-1aa097a2eef904db9b1842342e6c6f50" } ``` ## Delete a database ### Request ```http DELETE /data/:type/ HTTP/1.1 ``` ```http DELETE /data/io.cozy.events/ HTTP/1.1 ``` ### Response OK ```http HTTP/1.1 200 OK Content-Type: application/json ``` ```json { "ok": true, "deleted": true } ```