github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/docs/files.md (about) 1 [Table of contents](README.md#table-of-contents) 2 3 # Virtual File System 4 5 Cozy applications can use files for storing binary content, like photos or bills 6 in PDF. This service offers a REST API to manipulate easily without having to 7 know the underlying storage layer. The metadata are kept in CouchDB, but the 8 binaries can go to the local system, or a Swift instance. 9 10 ## Directories 11 12 A directory is a container for files and sub-directories. 13 14 Its path is the path of its parent, a slash (`/`), and its name. It's case 15 sensitive. 16 17 ### Root directory 18 19 The root of the virtual file system is a special directory with id 20 `io.cozy.files.root-dir`. 21 22 You can use it in any request where you would use a directory, except you cannot 23 delete it. 24 25 ### POST /files/:dir-id 26 27 Create a new directory. The `dir-id` parameter is optional. When it's not given, 28 the directory is created at the root of the virtual file system. 29 30 #### Query-String 31 32 | Parameter | Description | 33 | ---------- | ----------------------------------- | 34 | Type | `directory` | 35 | Name | the directory name | 36 | Tags | an array of tags | 37 | CreatedAt | the creation date | 38 | MetadataID | the identifier of a metadata object | 39 40 #### HTTP headers 41 42 | Parameter | Description | 43 | --------- | -------------------------------------- | 44 | Date | The modification date of the directory | 45 46 #### Request 47 48 ```http 49 POST /files/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81?Type=directory&Name=phone&Tags=bills,konnectors HTTP/1.1 50 Accept: application/vnd.api+json 51 Date: Mon, 19 Sep 2016 12:35:08 GMT 52 ``` 53 54 #### Status codes 55 56 - 201 Created, when the directory has been successfully created 57 - 404 Not Found, when the parent directory does not exist 58 - 409 Conflict, when a directory with the same name already exists 59 - 422 Unprocessable Entity, when the `Type`, `Name`, or `MetadataID` parameter 60 is missing or invalid 61 62 #### Response 63 64 ```http 65 HTTP/1.1 201 Created 66 Content-Type: application/vnd.api+json 67 Location: https://cozy.example.com/files/6494e0ac-dfcb-11e5-88c1-472e84a9cbee 68 ``` 69 70 ```json 71 { 72 "data": { 73 "type": "io.cozy.files", 74 "id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee", 75 "meta": { 76 "rev": "1-ff3beeb456eb" 77 }, 78 "attributes": { 79 "type": "directory", 80 "name": "phone", 81 "path": "/Documents/phone", 82 "created_at": "2016-09-19T12:35:08Z", 83 "updated_at": "2016-09-19T12:35:08Z", 84 "tags": ["bills", "konnectors"], 85 "cozyMetadata": { 86 "doctypeVersion": "1", 87 "metadataVersion": 1, 88 "createdAt": "2016-09-20T18:32:48Z", 89 "createdByApp": "drive", 90 "createdOn": "https://cozy.example.com/", 91 "updatedAt": "2016-09-20T18:32:48Z" 92 } 93 }, 94 "relationships": { 95 "parent": { 96 "links": { 97 "related": "/files/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81" 98 }, 99 "data": { 100 "type": "io.cozy.files", 101 "id": "fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81" 102 } 103 }, 104 "not_synchronized_on": { 105 "links": { 106 "self": "/files/6494e0ac-dfcb-11e5-88c1-472e84a9cbee/relationships/not_synchronized_on" 107 }, 108 "data": [ 109 { 110 "type": "io.cozy.oauth.clients", 111 "id": "653dfdb0-0595-0139-92df-543d7eb8149c" 112 } 113 ] 114 } 115 }, 116 "links": { 117 "self": "/files/6494e0ac-dfcb-11e5-88c1-472e84a9cbee" 118 } 119 } 120 } 121 ``` 122 123 **Note**: see [not synchronized directories](not-synchronized-vfs.md) for 124 more informations about the `not_synchronized_on` field. 125 126 ### POST /files/shared-drives 127 128 This endpoint returns the information about the Shared Drives directory. If the 129 directory does not exist, it is created. 130 131 #### Request 132 133 ```http 134 POST /files/shared-drives 135 Accept: application/vnd.api+json 136 ``` 137 138 #### Response 139 140 ```http 141 HTTP/1.1 201 Created 142 Content-Type: application/vnd.api+json 143 ``` 144 145 ```json 146 { 147 "data": { 148 "type": "io.cozy.files", 149 "id": "io.cozy.files.shared-drives-dir", 150 "meta": { 151 "rev": "1-e4abdb5a" 152 }, 153 "attributes": { 154 "type": "directory", 155 "name": "Shared drives", 156 "path": "/Shared drives", 157 "created_at": "2024-03-25T15:22:00Z", 158 "updated_at": "2024-03-25T15:22:00Z", 159 "cozyMetadata": { 160 "doctypeVersion": "1", 161 "metadataVersion": 1, 162 "createdAt": "2024-03-25T15:22:00Z", 163 "createdByApp": "drive", 164 "createdOn": "https://cozy.example.com/", 165 "updatedAt": "2024-03-25T15:22:00Z" 166 } 167 }, 168 "relationships": { 169 "parent": { 170 "links": { 171 "related": "/files/io.cozy.files.root-dir" 172 }, 173 "data": { 174 "type": "io.cozy.files", 175 "id": "io.cozy.files.root-dir" 176 } 177 } 178 }, 179 "links": { 180 "self": "/files/io.cozy.files.shared-drives-dir" 181 } 182 } 183 } 184 ``` 185 186 ### GET /files/:file-id 187 188 Get a directory or a file informations. In the case of a directory, it contains 189 the list of files and sub-directories inside it. For a note, its images are 190 included. 191 192 Contents is paginated following [jsonapi conventions](./http-api.md#pagination). 193 The default limit is 30 entries. 194 195 #### Request 196 197 ```http 198 GET /files/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81 HTTP/1.1 199 Accept: application/vnd.api+json 200 ``` 201 202 #### Response 203 204 ```http 205 HTTP/1.1 200 OK 206 Content-Type: application/vnd.api+json 207 ``` 208 209 ```json 210 { 211 "links": { 212 "next": "/files/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81?page[cursor]=9152d568-7e7c-11e6-a377-37cbfb190b4b" 213 }, 214 "data": { 215 "type": "io.cozy.files", 216 "id": "fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81", 217 "meta": { 218 "rev": "1-e36ab092" 219 }, 220 "attributes": { 221 "type": "directory", 222 "name": "Documents", 223 "path": "/Documents", 224 "created_at": "2016-09-19T12:35:00Z", 225 "updated_at": "2016-09-19T12:35:00Z", 226 "tags": [], 227 "cozyMetadata": { 228 "doctypeVersion": "1", 229 "metadataVersion": 1, 230 "createdAt": "2016-09-20T18:32:47Z", 231 "createdByApp": "drive", 232 "createdOn": "https://cozy.example.com/", 233 "updatedAt": "2016-09-20T18:32:47Z" 234 } 235 }, 236 "relationships": { 237 "contents": { 238 "data": [ 239 { 240 "type": "io.cozy.files", 241 "id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee" 242 }, 243 { 244 "type": "io.cozy.files", 245 "id": "9152d568-7e7c-11e6-a377-37cbfb190b4b" 246 } 247 ] 248 } 249 }, 250 "links": { 251 "self": "/files/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81" 252 } 253 }, 254 "included": [ 255 { 256 "type": "io.cozy.files", 257 "id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee", 258 "meta": { 259 "rev": "1-ff3beeb456eb" 260 }, 261 "attributes": { 262 "type": "directory", 263 "name": "phone", 264 "path": "/Documents/phone", 265 "created_at": "2016-09-19T12:35:08Z", 266 "updated_at": "2016-09-19T12:35:08Z", 267 "tags": ["bills", "konnectors"], 268 "cozyMetadata": { 269 "doctypeVersion": "1", 270 "metadataVersion": 1, 271 "createdAt": "2016-09-20T18:32:47Z", 272 "createdByApp": "drive", 273 "createdOn": "https://cozy.example.com/", 274 "updatedAt": "2016-09-20T18:32:47Z" 275 } 276 }, 277 "relationships": { 278 "parent": { 279 "links": { 280 "related": "/files/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81" 281 }, 282 "data": { 283 "type": "io.cozy.files", 284 "id": "fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81" 285 } 286 } 287 }, 288 "links": { 289 "self": "/files/6494e0ac-dfcb-11e5-88c1-472e84a9cbee" 290 } 291 }, 292 { 293 "type": "io.cozy.files", 294 "id": "9152d568-7e7c-11e6-a377-37cbfb190b4b", 295 "meta": { 296 "rev": "1-0e6d5b72" 297 }, 298 "attributes": { 299 "type": "file", 300 "name": "hello.txt", 301 "trashed": false, 302 "md5sum": "ODZmYjI2OWQxOTBkMmM4NQo=", 303 "created_at": "2016-09-19T12:38:04Z", 304 "updated_at": "2016-09-19T12:38:04Z", 305 "tags": [], 306 "size": 12, 307 "executable": false, 308 "class": "document", 309 "mime": "text/plain", 310 "cozyMetadata": { 311 "doctypeVersion": "1", 312 "metadataVersion": 1, 313 "createdAt": "2016-09-20T18:32:49Z", 314 "createdByApp": "drive", 315 "createdOn": "https://cozy.example.com/", 316 "updatedAt": "2016-09-20T18:32:49Z", 317 "uploadedAt": "2016-09-20T18:32:49Z", 318 "uploadedOn": "https://cozy.example.com/", 319 "uploadedBy": { 320 "slug": "drive" 321 } 322 } 323 }, 324 "relationships": { 325 "parent": { 326 "links": { 327 "related": "/files/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81" 328 }, 329 "data": { 330 "type": "io.cozy.files", 331 "id": "fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81" 332 } 333 } 334 }, 335 "links": { 336 "self": "/files/9152d568-7e7c-11e6-a377-37cbfb190b4b" 337 } 338 } 339 ] 340 } 341 ``` 342 343 ### GET /files/:file-id/size 344 345 This endpoint returns the size taken by the files in a directory, including 346 those in subdirectories. 347 348 #### Request 349 350 ```http 351 GET /files/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81/size HTTP/1.1 352 Accept: application/vnd.api+json 353 ``` 354 355 #### Response 356 357 ```http 358 HTTP/1.1 200 OK 359 Content-Type: application/vnd.api+json 360 ``` 361 362 ```json 363 { 364 "data": { 365 "type": "io.cozy.files.sizes", 366 "id": "fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81", 367 "attributes": { 368 "size": "1234567890" 369 }, 370 "meta": {} 371 } 372 } 373 ``` 374 375 ### GET `/files/_changes` 376 377 This endpoint is similar to the changes feed of CouchDB for io.cozy.files. 378 There are a few specificities: 379 380 - it is wrapped in the VFS lock to avoid seeing inconsistent results 381 - it automatically skips design docs 382 - if the requests is coming from an OAuth client, it excludes the files and directories that are in a not synchronized folder 383 - it only supports the options `since`, `limit`, and `include_docs` of CouchDB 384 - it has an option `fields` to only include those fields in the results 385 - it has an option `include_file_path` to add the `path` for files 386 - it has two options `skip_deleted` and `skip_trashed` to not send to the client the deleted/trashed files and directories. 387 388 ### Request 389 390 ```http 391 GET /files/_changes?include_docs=true&fields=type,name,dir_id&skip_deleted=true&limit=3 HTTP/1.1 392 ``` 393 394 ### Response 395 396 ```http 397 HTTP/1.1 200 OK 398 Content-Type: application/json 399 ``` 400 401 ```json 402 { 403 "last_seq": "13-g1AAAABHeJzLYWBgYMxgTmHgzcvPy09JdcjLz8gvLskBCjMlMuSxMPwHgqwM5kTeXKAQe5Jpmrl5ojG68iwA2MMV1A", 404 "pending": 24, 405 "results": [ 406 { 407 "id": "io.cozy.files.root-dir", 408 "seq": "11-g1AAAABHeJzLYWBgYMxgTmHgzcvPy09JdcjLz8gvLskBCjMlMuSxMPwHgqwM5kTuXKAQe5Jpmrl5ojG68iwA2IcV0g", 409 "doc": { 410 "type": "directory" 411 }, 412 "changes": [ 413 { 414 "rev": "1-077f26acac6f0a5e1022f109e8d1dfc4" 415 } 416 ] 417 }, 418 { 419 "id": "io.cozy.files.trash-dir", 420 "seq": "12-g1AAAABHeJzLYWBgYMxgTmHgzcvPy09JdcjLz8gvLskBCjMlMuSxMPwHgqwM5kSeXKAQe5Jpmrl5ojG68iwA2KUV0w", 421 "doc": { 422 "dir_id": "io.cozy.files.root-dir", 423 "name": ".cozy_trash", 424 "type": "directory" 425 }, 426 "changes": [ 427 { 428 "rev": "1-de9c11dbc386b5f91adbe2aee4a3e754" 429 } 430 ] 431 }, 432 { 433 "id": "d30b0dd6e0e8fefdac2a94cb2c00249f", 434 "seq": "13-g1AAAABHeJzLYWBgYMxgTmHgzcvPy09JdcjLz8gvLskBCjMlMuSxMPwHgqwM5kTeXKAQe5Jpmrl5ojG68iwA2MMV1A", 435 "doc": { 436 "dir_id": "io.cozy.files.root-dir", 437 "name": "Administratif", 438 "type": "directory" 439 }, 440 "changes": [ 441 { 442 "rev": "1-24f2828e8dbe64135913072a4c92d846" 443 } 444 ] 445 } 446 ] 447 } 448 ``` 449 450 ### POST `/files/_find` 451 452 Find allows to find documents using a mango selector. You can read more about mango selectors [here](http://docs.couchdb.org/en/stable/api/database/find.html#selector-syntax). 453 454 Note that it returns a 455 [bookmark](https://github.com/cozy/cozy-stack/blob/master/docs/mango.md#pagination-cookbook) 456 in the `links`, useful to paginate (following the [JSON-API 457 pagination](./http-api.md#pagination)). On the last page, there won't be a 458 `links.next`. 459 460 It is possible to pass a `execution_stats` parameter to get some information about the query execution. See [here](https://docs.couchdb.org/en/stable/api/database/find.html#execution-statistics) for more details. 461 462 ### Request 463 464 ```http 465 POST /files/_find HTTP/1.1 466 ``` 467 468 469 ```json 470 { 471 "selector": { 472 "class": "image", 473 "trashed": false 474 }, 475 "limit": 2, 476 "bookmark": "g1AAAABjeJzLYWBgYMpgSmHgKy5JLCrJTq2MT8lPzkzJBYorpFokG5qaGVqYmCWbGxuYGFkYWhgkmqaZJZsZGpibWhiA9HHA9OWATAJpY83MTUxPTWFgTUvMKU7NygIA7IYZzA", 477 "use_index": "_design/a5f4711fc9448864a13c81dc71e660b524d7410c", 478 "execution_stats": true 479 } 480 ``` 481 482 ### Response 483 484 ```http 485 HTTP/1.1 200 OK 486 Date: Mon, 27 Sept 2016 12:28:53 GMT 487 Content-Length: ... 488 Content-Type: application/json 489 ``` 490 491 ```json 492 { 493 "data": [ 494 { 495 "type": "io.cozy.files", 496 "id": "e8c1561846c730428180a5f6c6107914", 497 "attributes": { 498 "type": "file", 499 "name": "nicepic1.jpg", 500 "dir_id": "f49b4087cbf946dfc759214394009a6c", 501 "created_at": "2020-02-13T16:35:47.568155477+01:00", 502 "updated_at": "2020-02-13T16:35:47.568155477+01:00", 503 "size": "345385", 504 "md5sum": "12cGYwT+RiNjFxf4f7AmzQ==", 505 "mime": "image/jpeg", 506 "class": "image", 507 "executable": false, 508 "trashed": false, 509 "tags": [], 510 "path": "/Pictures/nicepic1.jpg", 511 "metadata": { 512 "datetime": "2020-02-13T16:35:47.568155477+01:00", 513 "extractor_version": 2, 514 "height": 1080, 515 "width": 1920 516 } 517 }, 518 "meta": { 519 "rev": "2-235e715b1d82a93285be1b0bd691b779" 520 }, 521 "links": { 522 "self": "/files/e8c1561846c730428180a5f6c6107914", 523 "tiny": "/files/e8c1561846c730428180a5f6c6107914/thumbnails/377327a8e20d6a50/tiny", 524 "small": "/files/e8c1561846c730428180a5f6c6107914/thumbnails/377327a8e20d6a50/small", 525 "medium": "/files/e8c1561846c730428180a5f6c6107914/thumbnails/377327a8e20d6a50/medium", 526 "large": "/files/e8c1561846c730428180a5f6c6107914/thumbnails/377327a8e20d6a50/large" 527 }, 528 "relationships": { 529 "parent": { 530 "links": { 531 "related": "/files/f49b4087cbf946dfc759214394009a6c" 532 }, 533 "data": { 534 "id": "f49b4087cbf946dfc759214394009a6c", 535 "type": "io.cozy.files" 536 } 537 } 538 } 539 }, 540 { 541 "type": "io.cozy.files", 542 "id": "e8c1561846c730428180a5f6c6109007", 543 "attributes": { 544 "type": "file", 545 "name": "nicepic2.jpg", 546 "dir_id": "f49b4087cbf946dfc759214394009a6c", 547 "created_at": "2020-02-13T16:35:47.845049743+01:00", 548 "updated_at": "2020-02-13T16:35:47.845049743+01:00", 549 "size": "323009", 550 "md5sum": "Fla3ucNXuW2Xw/TK8pfsPA==", 551 "mime": "image/jpeg", 552 "class": "image", 553 "executable": false, 554 "trashed": false, 555 "tags": [], 556 "path": "/Pictures/nicepic2.jpg", 557 "metadata": { 558 "datetime": "2020-02-13T16:35:47.845049743+01:00", 559 "extractor_version": 2, 560 "height": 1080, 561 "width": 1920 562 } 563 }, 564 "meta": { 565 "rev": "2-4883d6b8ccad32f8fb056af9b7f8b37f" 566 }, 567 "links": { 568 "self": "/files/e8c1561846c730428180a5f6c6109007", 569 "tiny": "/files/e8c1561846c730428180a5f6c6109007/thumbnails/58a4aea31b00c99d/tiny", 570 "small": "/files/e8c1561846c730428180a5f6c6109007/thumbnails/58a4aea31b00c99d/small", 571 "medium": "/files/e8c1561846c730428180a5f6c6109007/thumbnails/58a4aea31b00c99d/medium", 572 "large": "/files/e8c1561846c730428180a5f6c6109007/thumbnails/58a4aea31b00c99d/large" 573 }, 574 "relationships": { 575 "parent": { 576 "links": { 577 "related": "/files/f49b4087cbf946dfc759214394009a6c" 578 }, 579 "data": { 580 "id": "f49b4087cbf946dfc759214394009a6c", 581 "type": "io.cozy.files" 582 } 583 } 584 } 585 } 586 ], 587 "links": { 588 "next": "/files/_find?page[cursor]=g1AAAABjeJzLYWBgYMpgSmHgKy5JLCrJTq2MT8lPzkzJBYorpFokG5qaGVqYmCWbGxuYGFkYWhgkmqaZJZsZGlgaGJiD9HHA9OWATAJpY83MTUxPTWFgTUvMKU7NygIA694ZyA" 589 }, 590 "meta": { 591 "count": 2, 592 "execution_stats": { 593 "total_docs_examined": 11, 594 "results_returned": 2, 595 "execution_time_ms": 8.833 596 } 597 } 598 } 599 ``` 600 601 602 ### DELETE /files/:dir-id 603 604 Put a directory and its subtree in the trash. It requires the permissions on 605 `io.cozy.files` for `PATCH`. 606 607 #### HTTP headers 608 609 It's possible to send the `If-Match` header, with the previous revision of the 610 file/directory (optional). 611 612 ## Files 613 614 A file is a binary content with some metadata. 615 616 ### POST /files/:dir-id 617 618 Upload a file in the directory identified by `:dir-id`. 619 620 The `created_at` field will be the first valid value in this list: 621 622 - the datetime extracted from the EXIF for a photo 623 - the `CreatedAt` parameter from the query-string 624 - the `Date` HTTP header 625 - the current time from the server. 626 627 The `updated_at` field will be the first value in this list: 628 629 - the datetime extracted from the EXIF for a photo if it is greater than the other values 630 - the `UpdatedAt` parameter from the query-string 631 - the `Date` HTTP header 632 - the current time from the server. 633 634 /!\ If the `updated_at` field is older than the `created_at` one, 635 then the `updated_at` will be set with the value of the `created_at`. 636 637 #### Query-String 638 639 | Parameter | Description | 640 | ----------------------- | -------------------------------------------------------------- | 641 | Type | `file` | 642 | Name | the file name | 643 | Size | the file size (when `Content-Length` can't be used) | 644 | Tags | an array of tags | 645 | Executable | `true` if the file is executable (UNIX permission) | 646 | Encrypted | `true` if the file is client-side encrypted | 647 | Metadata | a JSON with metadata on this file (_not recommended_) | 648 | MetadataID | the identifier of a metadata object | 649 | CreatedAt | the creation date of the file | 650 | UpdatedAt | the modification date of the file | 651 | SourceAccount | the id of the source account used by a konnector | 652 | SourceAccountIdentifier | the unique identifier of the account targeted by the connector | 653 654 #### HTTP headers 655 656 | Parameter | Description | 657 | -------------- | ------------------------------------------- | 658 | Content-Length | The file size | 659 | Content-MD5 | A Base64-encoded binary MD5 sum of the file | 660 | Content-Type | The mime-type of the file | 661 | Date | The modification date of the file | 662 663 #### Request 664 665 ```http 666 POST /files/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81?Type=file&Name=hello.txt&CreatedAt=2016-09-18T01:23:45Z HTTP/1.1 667 Accept: application/vnd.api+json 668 Content-Length: 12 669 Content-MD5: hvsmnRkNLIX24EaM7KQqIA== 670 Content-Type: text/plain 671 Date: Mon, 19 Sep 2016 12:38:04 GMT 672 Host: cozy.example.com 673 674 Hello world! 675 ``` 676 677 #### Status codes 678 679 - 201 Created, when the file has been successfully created 680 - 404 Not Found, when the parent directory does not exist 681 - 409 Conflict, when a file with the same name already exists 682 - 412 Precondition Failed, when the md5sum is `Content-MD5` is not equal to 683 the md5sum computed by the server 684 - 413 Payload Too Large, when there is not enough available space on the cozy 685 to upload the file or the file is larger than the server's filesystem maximum 686 file size 687 - 422 Unprocessable Entity, when the sent data is invalid (for example, the 688 parent doesn't exist, `Type`, `Name`, or `MetadataID` parameter is missing or 689 invalid, etc.) 690 691 #### Response 692 693 ```http 694 HTTP/1.1 201 Created 695 Content-Type: application/vnd.api+json 696 Location: https://cozy.example.com/files/9152d568-7e7c-11e6-a377-37cbfb190b4b 697 ``` 698 699 ```json 700 { 701 "data": { 702 "type": "io.cozy.files", 703 "id": "9152d568-7e7c-11e6-a377-37cbfb190b4b", 704 "meta": { 705 "rev": "4-1482b88a" 706 }, 707 "attributes": { 708 "type": "file", 709 "name": "sunset.jpg", 710 "trashed": false, 711 "md5sum": "ODZmYjI2OWQxOTBkMmM4NQo=", 712 "created_at": "2016-09-18T20:38:04Z", 713 "updated_at": "2016-09-21T12:38:04Z", 714 "tags": [], 715 "metadata": { 716 "datetime": "2016-09-18T20:38:04Z", 717 "height": 1080, 718 "width": 1920 719 }, 720 "size": 12, 721 "executable": false, 722 "class": "image", 723 "mime": "image/jpg", 724 "cozyMetadata": { 725 "doctypeVersion": "1", 726 "metadataVersion": 1, 727 "createdAt": "2016-09-20T18:32:49Z", 728 "createdByApp": "drive", 729 "createdOn": "https://cozy.example.com/", 730 "updatedAt": "2016-09-21T14:46:37Z", 731 "uploadedAt": "2016-09-20T18:37:52Z", 732 "uploadedOn": "https://cozy.example.com/", 733 "uploadedBy": { 734 "slug": "drive" 735 } 736 } 737 }, 738 "relationships": { 739 "parent": { 740 "links": { 741 "related": "/files/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81" 742 }, 743 "data": { 744 "type": "io.cozy.files", 745 "id": "fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81" 746 } 747 }, 748 "referenced_by": { 749 "links": { 750 "self": "/files/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81/relationships/references" 751 }, 752 "data": [ 753 { 754 "type": "io.cozy.albums", 755 "id": "94375086-e2e2-11e6-81b9-5bc0b9dd4aa4" 756 } 757 ] 758 }, 759 "old_versions": { 760 "data": [ 761 { 762 "type": "io.cozy.files.versions", 763 "id": "9152d568-7e7c-11e6-a377-37cbfb190b4b/2-fa3a3bec" 764 }, 765 { 766 "type": "io.cozy.files.versions", 767 "id": "9152d568-7e7c-11e6-a377-37cbfb190b4b/1-0e6d5b72" 768 } 769 ] 770 } 771 }, 772 "links": { 773 "self": "/files/9152d568-7e7c-11e6-a377-37cbfb190b4b", 774 "tiny": "/files/9152d568-7e7c-11e6-a377-37cbfb190b4b/thumbnails/0f9cda56674282ac/tiny", 775 "small": "/files/9152d568-7e7c-11e6-a377-37cbfb190b4b/thumbnails/0f9cda56674282ac/small", 776 "medium": "/files/9152d568-7e7c-11e6-a377-37cbfb190b4b/thumbnails/0f9cda56674282ac/medium", 777 "large": "/files/9152d568-7e7c-11e6-a377-37cbfb190b4b/thumbnails/0f9cda56674282ac/large" 778 } 779 }, 780 "included": [ 781 { 782 "type": "io.cozy.files.versions", 783 "id": "9152d568-7e7c-11e6-a377-37cbfb190b4b/2-fa3a3bec", 784 "meta": { 785 "rev": "1-26a331" 786 }, 787 "attributes": { 788 "file_id": "9152d568-7e7c-11e6-a377-37cbfb190b4b", 789 "updated_at": "2016-09-21T10:11:12Z", 790 "md5sum": "a2lth5syMW+4r7jwNhdk3A==", 791 "size": 123456, 792 "tags": [], 793 "cozyMetadata": { 794 "doctypeVersion": "1", 795 "metadataVersion": 1, 796 "createdAt": "2016-09-20T18:37:52Z", 797 "createdByApp": "drive", 798 "createdOn": "https://cozy.example.com/", 799 "updatedAt": "2016-09-20T18:37:52Z", 800 "uploadedAt": "2016-09-20T18:37:52Z", 801 "uploadedOn": "https://cozy.example.com/", 802 "uploadedBy": { 803 "slug": "drive" 804 } 805 } 806 } 807 }, 808 { 809 "type": "io.cozy.files.versions", 810 "id": "9152d568-7e7c-11e6-a377-37cbfb190b4b/1-0e6d5b72", 811 "meta": { 812 "rev": "1-57b3e2" 813 }, 814 "attributes": { 815 "file_id": "9152d568-7e7c-11e6-a377-37cbfb190b4b", 816 "updated_at": "2016-09-18T20:38:04Z", 817 "md5sum": "FBA89XXOZKFhdv37iILb2Q==", 818 "size": 159753, 819 "tags": [], 820 "cozyMetadata": { 821 "doctypeVersion": "1", 822 "metadataVersion": 1, 823 "createdAt": "2016-09-20T18:32:49Z", 824 "createdByApp": "drive", 825 "createdOn": "https://cozy.example.com/", 826 "updatedAt": "2016-09-20T18:32:49Z", 827 "uploadedAt": "2016-09-20T18:32:49Z", 828 "uploadedOn": "https://cozy.example.com/", 829 "uploadedBy": { 830 "slug": "drive" 831 } 832 } 833 } 834 } 835 ] 836 } 837 ``` 838 839 **Note**: see [references of documents in VFS](references-docs-in-vfs.md) for 840 more informations about the references field. 841 842 ### POST /files/upload/metadata 843 844 Send a metadata object that can be associated to a file (or directory) uploaded 845 after that, via the `MetadataID` query parameter. The `MetadataID` parameter is 846 only valid for 10 minutes, and will expire after that. 847 848 **Note:** a special permission on `io.cozy.certified.carbon_copy` is required 849 to send a request with `carbonCopy` as key in the `attributes` map. Same for 850 `electronicSafe`. 851 852 See the [metadata doctype](https://docs.cozy.io/en/cozy-doctypes/docs/io.cozy.files_metadata/) to know more about metadata attributes that can be set, notably for images and document qualification. 853 854 #### Request 855 856 ```http 857 POST /files/upload/metadata HTTP/1.1 858 Content-Type: application/vnd.api+json 859 ``` 860 861 ```json 862 { 863 "data": { 864 "type": "io.cozy.files.metadata", 865 "attributes": { 866 "qualification": { 867 "label": "telecom_invoice", 868 "purpose": "invoice", 869 "sourceCategory": "telecom" 870 }, 871 "datetime": "2017-04-22T01:00:00-05:00" 872 } 873 } 874 } 875 ``` 876 877 #### Response 878 879 ```http 880 HTTP/1.1 201 Created 881 Content-Type: application/vnd.api+json 882 ``` 883 884 ```json 885 { 886 "data": { 887 "type": "io.cozy.files.metadata", 888 "id": "42E6BD48", 889 "attributes": { 890 "qualification": { 891 "label": "telecom_invoice", 892 "purpose": "invoice", 893 "sourceCategory": "telecom" 894 }, 895 "datetime": "2017-04-22T01:00:00-05:00" 896 } 897 } 898 } 899 ``` 900 901 ### GET /files/download/:file-id 902 903 Download the file content. 904 905 By default the `content-disposition` will be `inline`, but it will be 906 `attachment` if the query string contains the parameter `Dl=1` 907 908 #### Request 909 910 ```http 911 GET /files/download/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81 HTTP/1.1 912 ``` 913 914 #### Response 915 916 ```http 917 HTTP/1.1 200 OK 918 Content-Length: 12 919 Content-Disposition: inline; filename="hello.txt" 920 Content-Type: text/plain 921 922 Hello world! 923 ``` 924 925 ### GET /files/download 926 927 Download the file content from its path. 928 929 By default the `content-disposition` will be `inline`, but it will be 930 `attachment` if the query string contains the parameter `Dl=1` 931 932 #### Request 933 934 ```http 935 GET /files/download?Path=/Documents/hello.txt&Dl=1 HTTP/1.1 936 ``` 937 938 ### GET /files/:file-id/icon/:secret 939 940 Get an image that shows the first page of a PDF in a small resolution (96x96). 941 942 **Note:** this route is deprecated, you should use thumbnails instead. 943 944 ### GET /files/:file-id/preview/:secret 945 946 Get an image that shows the first page of a PDF (at most 1080x1920). 947 948 **Note:** this route is deprecated, you should use thumbnails instead. 949 950 ### GET /files/:file-id/thumbnails/:secret/:format 951 952 Get a thumbnail of a file (for an image & pdf only). `:format` can be `tiny` (96x96) 953 `small` (640x480), `medium` (1280x720), or `large` (1920x1080). 954 955 This API does not require authentication because the secret acts as a token. 956 This secret is valid for 10 minutes, after which the link will return an error. 957 To retrieve a new functional link, you must query the files API again to obtain 958 a new secret. 959 960 ### PUT /files/:file-id 961 962 Overwrite a file 963 964 The `updated_at` field will be the first value in this list: 965 966 - the datetime extracted from the EXIF for a photo if it is greater than the other values 967 - the `UpdatedAt` parameter from the query-string 968 - the `Date` HTTP header 969 - the current time from the server. 970 971 /!\ If the `updated_at` field is older than the `created_at` one, then the 972 `updated_at` will be set with the value of the `created_at`. 973 974 #### Query-String 975 976 | Parameter | Description | 977 | ----------------------- | -------------------------------------------------------------- | 978 | Size | the file size (when `Content-Length` can't be used) | 979 | Tags | an array of tags | 980 | Executable | `true` if the file is executable (UNIX permission) | 981 | Encrypted | `true` if the file is client-side encrypted | 982 | MetadataID | the identifier of a metadata object | 983 | UpdatedAt | the modification date of the file | 984 | SourceAccount | the id of the source account used by a konnector | 985 | SourceAccountIdentifier | the unique identifier of the account targeted by the connector | 986 987 #### HTTP headers 988 989 The HTTP headers are the same than for uploading a file. There is one additional 990 header, `If-Match`, with the previous revision of the file (optional). 991 992 #### Request 993 994 ```http 995 PUT /files/9152d568-7e7c-11e6-a377-37cbfb190b4b HTTP/1.1 996 Accept: application/vnd.api+json 997 Content-Length: 12 998 Content-MD5: hvsmnRkNLIX24EaM7KQqIA== 999 Content-Type: text/plain 1000 If-Match: 1-0e6d5b72 1001 1002 HELLO WORLD! 1003 ``` 1004 1005 #### Status codes 1006 1007 - 200 OK, when the file has been successfully overwritten 1008 - 404 Not Found, when the file wasn't existing 1009 - 412 Precondition Failed, when the `If-Match` header is set and doesn't match 1010 the last revision of the file 1011 - 413 Payload Too Large, when there is not enough available space on the cozy 1012 to upload the file or the file is larger than the server's filesystem maximum 1013 file size 1014 - 422 Unprocessable Entity, when the sent data is invalid (for example, the 1015 `MetadataID` parameter has expired) 1016 1017 #### Response 1018 1019 ```http 1020 HTTP/1.1 200 OK 1021 Content-Type: application/vnd.api+json 1022 ``` 1023 1024 ```json 1025 { 1026 "data": { 1027 "type": "io.cozy.files", 1028 "id": "9152d568-7e7c-11e6-a377-37cbfb190b4b", 1029 "meta": { 1030 "rev": "2-d903b54c" 1031 }, 1032 "attributes": { 1033 "type": "file", 1034 "name": "hello.pdf", 1035 "trashed": false, 1036 "md5sum": "YjU5YmMzN2Q2NDQxZDk2Nwo=", 1037 "created_at": "2016-09-19T12:38:04Z", 1038 "updated_at": "2016-09-19T12:38:04Z", 1039 "tags": [], 1040 "size": 12, 1041 "executable": false, 1042 "class": "pdf", 1043 "mime": "application/pdf", 1044 "cozyMetadata": { 1045 "doctypeVersion": "1", 1046 "metadataVersion": 1, 1047 "createdAt": "2016-09-20T18:32:49Z", 1048 "createdByApp": "drive", 1049 "createdOn": "https://cozy.example.com/", 1050 "updatedAt": "2016-09-21T04:27:50Z", 1051 "uploadedAt": "2016-09-21T04:27:50Z", 1052 "uploadedOn": "https://cozy.example.com/", 1053 "uploadedBy": { 1054 "slug": "drive" 1055 } 1056 } 1057 }, 1058 "relationships": { 1059 "parent": { 1060 "links": { 1061 "related": "/files/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81" 1062 }, 1063 "data": { 1064 "type": "io.cozy.files", 1065 "id": "fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81" 1066 } 1067 } 1068 }, 1069 "links": { 1070 "self": "/files/9152d568-7e7c-11e6-a377-37cbfb190b4b", 1071 "icon": "/files/9152d568-7e7c-11e6-a377-37cbfb190b4b/icon/543d7eb8", 1072 "preview": "/files/9152d568-7e7c-11e6-a377-37cbfb190b4b/preview/77e117e0", 1073 "tiny": "/files/9152d568-7e7c-11e6-a377-37cbfb190b4b/thumbnails/93fd0a5d96b22e9d/tiny", 1074 "small": "/files/9152d568-7e7c-11e6-a377-37cbfb190b4b/thumbnails/93fd0a5d96b22e9d/small", 1075 "medium": "/files/9152d568-7e7c-11e6-a377-37cbfb190b4b/thumbnails/93fd0a5d96b22e9d/medium", 1076 "large": "/files/9152d568-7e7c-11e6-a377-37cbfb190b4b/thumbnails/93fd0a5d96b22e9d/large" 1077 } 1078 } 1079 } 1080 ``` 1081 1082 ### POST /files/:file-id/copy 1083 1084 Create a copy of a file in the same directory with a copy suffix in its name 1085 1086 #### Query-String 1087 1088 | Parameter | Description | 1089 | ---------- | -------------------------------------------------- | 1090 | Name | the file copy name (optional) | 1091 | DirID | the destination directory id (optional) | 1092 1093 #### Request 1094 1095 ```http 1096 POST /files/9152d568-7e7c-11e6-a377-37cbfb190b4b/copy HTTP/1.1 1097 Accept: application/vnd.api+json 1098 ``` 1099 1100 #### Status codes 1101 1102 - 201 Created, when the file has been successfully copied 1103 - 404 Not Found, when the file does not exist 1104 - 409 Conflict, when a file with the same name as the copy would have already exists 1105 - 413 Payload Too Large, when there is not enough available space on the cozy 1106 to copy the file 1107 1108 #### Response 1109 1110 ```http 1111 HTTP/1.1 201 Created 1112 Content-Type: application/vnd.api+json 1113 ``` 1114 1115 ```json 1116 { 1117 "data": { 1118 "type": "io.cozy.files", 1119 "id": "7382f28a-21d4-12d9-4438-3fd53e98a219", 1120 "meta": { 1121 "rev": "1-83a82e9" 1122 }, 1123 "attributes": { 1124 "type": "file", 1125 "name": "hello (copy).pdf", 1126 "trashed": false, 1127 "md5sum": "YjU5YmMzN2Q2NDQxZDk2Nwo=", 1128 "created_at": "2022-10-18T18:33:24Z", 1129 "updated_at": "2022-10-18T18:33:24Z", 1130 "tags": [], 1131 "size": 12, 1132 "executable": false, 1133 "class": "pdf", 1134 "mime": "application/pdf", 1135 "cozyMetadata": { 1136 "doctypeVersion": "1", 1137 "metadataVersion": 1, 1138 "createdAt": "2022-10-18T18:33:24Z", 1139 "createdByApp": "drive", 1140 "createdOn": "https://cozy.example.com/", 1141 "updatedAt": "2022-10-18T18:33:24Z" 1142 } 1143 }, 1144 "relationships": { 1145 "parent": { 1146 "links": { 1147 "related": "/files/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81" 1148 }, 1149 "data": { 1150 "type": "io.cozy.files", 1151 "id": "fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81" 1152 } 1153 } 1154 }, 1155 "links": { 1156 "self": "/files/7382f28a-21d4-12d9-4438-3fd53e98a219", 1157 "icon": "/files/7382f28a-21d4-12d9-4438-3fd53e98a219/icon/543d7eb8", 1158 "preview": "/files/7382f28a-21d4-12d9-4438-3fd53e98a219/preview/77e117e0", 1159 "tiny": "/files/7382f28a-21d4-12d9-4438-3fd53e98a219/thumbnails/93fd0a5d96b22e9d/tiny", 1160 "small": "/files/7382f28a-21d4-12d9-4438-3fd53e98a219/thumbnails/93fd0a5d96b22e9d/small", 1161 "medium": "/files/7382f28a-21d4-12d9-4438-3fd53e98a219/thumbnails/93fd0a5d96b22e9d/medium", 1162 "large": "/files/7382f28a-21d4-12d9-4438-3fd53e98a219/thumbnails/93fd0a5d96b22e9d/large" 1163 } 1164 } 1165 } 1166 ``` 1167 1168 ### DELETE /files/:file-id 1169 1170 Put a file in the trash. 1171 1172 ## Common 1173 1174 ### GET /files/metadata 1175 1176 Same as `/files/:file-id` but to retrieve informations from a path. 1177 1178 #### Request 1179 1180 ```http 1181 GET /files/metadata?Path=/Documents/hello.txt HTTP/1.1 1182 ``` 1183 1184 #### Response 1185 1186 ```http 1187 HTTP/1.1 200 OK 1188 Content-Type: application/vnd.api+json 1189 Location: https://cozy.example.com/files/9152d568-7e7c-11e6-a377-37cbfb190b4b 1190 ``` 1191 1192 ```json 1193 { 1194 "data": { 1195 "type": "io.cozy.files", 1196 "id": "9152d568-7e7c-11e6-a377-37cbfb190b4b", 1197 "meta": { 1198 "rev": "1-0e6d5b72" 1199 }, 1200 "attributes": { 1201 "type": "file", 1202 "name": "hello.txt", 1203 "trashed": false, 1204 "md5sum": "ODZmYjI2OWQxOTBkMmM4NQo=", 1205 "created_at": "2016-09-19T12:38:04Z", 1206 "updated_at": "2016-09-19T12:38:04Z", 1207 "tags": [], 1208 "size": 12, 1209 "executable": false, 1210 "class": "document", 1211 "mime": "text/plain", 1212 "cozyMetadata": { 1213 "doctypeVersion": "1", 1214 "metadataVersion": 1, 1215 "createdAt": "2016-09-20T18:32:49Z", 1216 "createdByApp": "drive", 1217 "createdOn": "https://cozy.example.com/", 1218 "updatedAt": "2016-09-20T18:32:49Z", 1219 "uploadedAt": "2016-09-20T18:32:49Z", 1220 "uploadedOn": "https://cozy.example.com/", 1221 "uploadedBy": { 1222 "slug": "drive" 1223 } 1224 } 1225 }, 1226 "relationships": { 1227 "parent": { 1228 "links": { 1229 "related": "/files/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81" 1230 }, 1231 "data": { 1232 "type": "io.cozy.files", 1233 "id": "fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81" 1234 } 1235 } 1236 }, 1237 "links": { 1238 "self": "/files/9152d568-7e7c-11e6-a377-37cbfb190b4b" 1239 } 1240 } 1241 } 1242 ``` 1243 1244 ### PATCH /files/:file-id and PATCH /files/metadata 1245 1246 Both endpoints can be used to update the metadata of a file or directory, or to 1247 rename/move it. The difference is the first one uses an id to identify the 1248 file/directory to update, and the second one uses the path. 1249 1250 Some specific attributes of the patch can be used: 1251 1252 - `dir_id` attribute can be updated to move a file or directory 1253 - `move_to_trash` boolean to specify that the file needs to be moved to the 1254 trash 1255 - `permanent_delete` boolean to specify that the files needs to be deleted 1256 (after being trashed) 1257 - `cozyMetadata.favorite` boolean attribute to put/remove a file from the 1258 favorites 1259 1260 #### HTTP headers 1261 1262 It's possible to send the `If-Match` header, with the previous revision of the 1263 file/directory (optional). 1264 1265 #### Request 1266 1267 ```http 1268 PATCH /files/9152d568-7e7c-11e6-a377-37cbfb190b4b HTTP/1.1 1269 Accept: application/vnd.api+json 1270 Content-Type: application/vnd.api+json 1271 ``` 1272 1273 ```json 1274 { 1275 "data": { 1276 "type": "io.cozy.files", 1277 "id": "9152d568-7e7c-11e6-a377-37cbfb190b4b", 1278 "attributes": { 1279 "type": "file", 1280 "name": "hi.txt", 1281 "dir_id": "f2f36fec-8018-11e6-abd8-8b3814d9a465", 1282 "tags": ["poem"], 1283 "cozyMetadata": { 1284 "favorite": true 1285 } 1286 } 1287 } 1288 } 1289 ``` 1290 1291 #### Status codes 1292 1293 - 200 OK, when the file or directory metadata has been successfully updated 1294 - 400 Bad Request, when a the directory is asked to move to one of its 1295 sub-directories 1296 - 404 Not Found, when the file/directory wasn't existing 1297 - 412 Precondition Failed, when the `If-Match` header is set and doesn't match 1298 the last revision of the file/directory 1299 - 422 Unprocessable Entity, when the sent data is invalid (for example, the 1300 parent doesn't exist) 1301 1302 #### Response 1303 1304 ```http 1305 HTTP/1.1 200 OK 1306 Content-Type: application/vnd.api+json 1307 Location: https://cozy.example.com/files/9152d568-7e7c-11e6-a377-37cbfb190b4b 1308 ``` 1309 1310 ```json 1311 { 1312 "data": { 1313 "type": "io.cozy.files", 1314 "id": "9152d568-7e7c-11e6-a377-37cbfb190b4b", 1315 "meta": { 1316 "rev": "1-0e6d5b72" 1317 }, 1318 "attributes": { 1319 "type": "file", 1320 "name": "hi.txt", 1321 "trashed": false, 1322 "md5sum": "ODZmYjI2OWQxOTBkMmM4NQo=", 1323 "created_at": "2016-09-19T12:38:04Z", 1324 "updated_at": "2016-09-19T12:38:04Z", 1325 "tags": ["poem"], 1326 "size": 12, 1327 "executable": false, 1328 "class": "document", 1329 "mime": "text/plain", 1330 "cozyMetadata": { 1331 "doctypeVersion": "1", 1332 "metadataVersion": 1, 1333 "createdAt": "2016-09-20T18:32:49Z", 1334 "createdByApp": "drive", 1335 "createdOn": "https://cozy.example.com/", 1336 "updatedAt": "2016-09-22T13:32:51Z", 1337 "uploadedAt": "2016-09-21T04:27:50Z", 1338 "uploadedOn": "https://cozy.example.com/", 1339 "uploadedBy": { 1340 "slug": "drive" 1341 } 1342 } 1343 }, 1344 "relationships": { 1345 "parent": { 1346 "links": { 1347 "related": "/files/f2f36fec-8018-11e6-abd8-8b3814d9a465" 1348 }, 1349 "data": { 1350 "type": "io.cozy.files", 1351 "id": "f2f36fec-8018-11e6-abd8-8b3814d9a465" 1352 } 1353 } 1354 }, 1355 "links": { 1356 "self": "/files/9152d568-7e7c-11e6-a377-37cbfb190b4b" 1357 } 1358 } 1359 } 1360 ``` 1361 1362 ### PATCH /files/ 1363 1364 Endpoint to update the metadata of files and directories in batch. It can be 1365 used, for instance, to move many files in a single request. 1366 1367 #### Request 1368 1369 ```http 1370 PATCH /files/ HTTP/1.1 1371 Content-Type: application/vnd.api+json 1372 ``` 1373 1374 ```json 1375 { 1376 "data": [ 1377 { 1378 "type": "io.cozy.files", 1379 "id": "9152d568-7e7c-11e6-a377-37cbfb190b4b", 1380 "meta": {"rev": "1-0e6d5b72"}, 1381 "attributes": {"dir_id": "f2f36fec-8018-11e6-abd8-8b3814d9a465"} 1382 }, 1383 { 1384 "type": "io.cozy.files", 1385 "id": "9152d568-7e7c-11e6-a377-37cbfb190b4c", 1386 "meta": {"rev": "2-123123"}, 1387 "attributes": {"move_to_trash": true} 1388 } 1389 ] 1390 } 1391 ``` 1392 1393 #### Status codes 1394 1395 The same status codes can be encountered as the `PATCH /files/:file-id` route. 1396 1397 ### POST /files/archive 1398 1399 Create an archive. The body of the request lists the files and directories that 1400 will be included in the archive. For directories, it includes all the files and 1401 sub-directories in the archive. 1402 1403 It's possible to give a file by its id (in the `ids` array) or by its path (in 1404 the `files` array). 1405 1406 The generated archive is temporary and is not persisted. 1407 1408 #### Request 1409 1410 ```http 1411 POST /files/archive HTTP/1.1 1412 Content-Type: application/vnd.api+json 1413 ``` 1414 1415 ```json 1416 { 1417 "data": { 1418 "type": "io.cozy.files.archives", 1419 "attributes": { 1420 "name": "project-X", 1421 "ids": ["a51aeeea-4f79-11e7-9dc4-83f67e9494ab"], 1422 "files": [ 1423 "/Documents/bills", 1424 "/Documents/images/sunset.jpg", 1425 "/Documents/images/eiffel-tower.jpg" 1426 ] 1427 } 1428 } 1429 } 1430 ``` 1431 1432 #### Response 1433 1434 ```http 1435 HTTP/1.1 200 OK 1436 Content-Type: application/vnd.api+json 1437 ``` 1438 1439 ```json 1440 { 1441 "links": { 1442 "related": "/files/archive/4521DC87/project-X.zip" 1443 }, 1444 "data": { 1445 "type": "io.cozy.files.archives", 1446 "id": "4521DC87", 1447 "attributes": { 1448 "href": "/files/archive/4521DC87/project-X.zip" 1449 } 1450 } 1451 } 1452 ``` 1453 1454 ### GET /files/archive/:key/:name 1455 1456 Download a previously created archive. The name parameter is not used in the 1457 stack but aims to allow setting a name even for browser / downloader that do not 1458 support Content-Disposition filename. 1459 1460 **This route does not require Basic Authentification** 1461 1462 ```http 1463 GET /files/archive/4521DC87/project-X.zip HTTP/1.1 1464 Accept: application/zip 1465 Content-Length: 12345 1466 Content-Disposition: attachment; filename="project-X.zip" 1467 Content-Type: application/zip 1468 ``` 1469 1470 ### POST /files/downloads?Path=file_path 1471 1472 Create a file download. The Path query parameter specifies the file to download. 1473 The response json API links contains a `related` link for downloading the file, 1474 see below. 1475 1476 ### POST /files/downloads?Id=file_id 1477 1478 Also create a file download. But it takes the id of the file and not its path. 1479 1480 ### POST /files/downloads?VersionId=file_id/version_id 1481 1482 This is a third way to create a file download. But, this time, it is for 1483 downloading an old version of a file. 1484 1485 These 3 routes also accept a `Filename=...` parameter in the query-string to 1486 change the filename that will be used for the downloaded file. 1487 1488 ### GET /files/downloads/:secret/:name 1489 1490 Allows to download a file with a secret created from the route above. 1491 1492 The name parameter is not used in the stack but aims to allow setting a name 1493 even for browser / downloader that do not support Content-Disposition filename. 1494 1495 By default the `content-disposition` will be `inline`, but it will be 1496 `attachment` if the query string contains the parameter `Dl=1` 1497 1498 **This route does not require Basic Authentification** 1499 1500 ## Versions 1501 1502 The identifier of the `io.cozy.files.versions` is composed of the `file-id` and 1503 another string called the `version-id`, separated by a `/`. So, when a route 1504 makes reference to `/something/:file-id/:version-id`, you can use the identifier 1505 of the version document (without having to prepend the file identifier). 1506 1507 ### GET /files/download/:file-id/:version-id 1508 1509 Download an old version of the file content 1510 1511 By default the `content-disposition` will be `inline`, but it will be 1512 `attachment` if the query string contains the parameter `Dl=1` 1513 1514 #### Request 1515 1516 ```http 1517 GET /files/download/9152d568-7e7c-11e6-a377-37cbfb190b4b/1-0e6d5b72 HTTP/1.1 1518 ``` 1519 1520 ### POST /files/:file-id/versions 1521 1522 Create a new version of a file, with the same content but new metadata. It 1523 requires a permission for PUT on the file, as it is equivalent to upload the 1524 same content of the file. 1525 1526 #### Query-String 1527 1528 | Parameter | Description | 1529 | --------- | ------------------ | 1530 | Tags | an array of tags | 1531 1532 #### Request 1533 1534 ```http 1535 POST /files/9152d568-7e7c-11e6-a377-37cbfb190b4b/metadata HTTP/1.1 1536 Content-Type: application/vnd.api+json 1537 ``` 1538 1539 ```json 1540 { 1541 "data": { 1542 "type": "io.cozy.files.metadata", 1543 "attributes": { 1544 "qualification": { 1545 "label": "telecom_invoice", 1546 "purpose": "invoice", 1547 "sourceCategory": "telecom" 1548 }, 1549 "datetime": "2017-04-22T01:00:00-05:00", 1550 } 1551 } 1552 } 1553 ``` 1554 1555 ### POST /files/revert/:file-id/:version-id 1556 1557 This endpoint can be used to revert to an old version of the content for a 1558 file. 1559 1560 #### Request 1561 1562 ```http 1563 POST /files/revert/9152d568-7e7c-11e6-a377-37cbfb190b4b/2-fa3a3bec HTTP/1.1 1564 ``` 1565 1566 ### PATCH /files/:file-id/:version-id 1567 1568 This endpoint can be used to edit the tags of a previous version of the file. 1569 1570 #### Request 1571 1572 ```http 1573 PATCH /files/9152d568-7e7c-11e6-a377-37cbfb190b4b/1-0e6d5b72 HTTP/1.1 1574 Accept: application/vnd.api+json 1575 Content-Type: application/vnd.api+json 1576 ``` 1577 1578 1579 ```json 1580 { 1581 "data": { 1582 "type": "io.cozy.files.versions", 1583 "id": "9152d568-7e7c-11e6-a377-37cbfb190b4b/1-0e6d5b72", 1584 "attributes": { 1585 "tags": ["poem"] 1586 } 1587 } 1588 } 1589 ``` 1590 1591 ### DELETE /files/:file-id/:version-id 1592 1593 This endpoint can be used to delete an old version of the content for a file. 1594 1595 #### Request 1596 1597 ```http 1598 DELETE /files/9152d568-7e7c-11e6-a377-37cbfb190b4b/2-fa3a3bec HTTP/1.1 1599 ``` 1600 1601 #### Response 1602 1603 ```http 1604 HTTP/1.1 204 No Content 1605 ``` 1606 1607 ### DELETE /files/versions 1608 1609 Deletes all the old versions of all files to make space for new files. 1610 1611 #### Request 1612 1613 ```http 1614 DELETE /files/versions HTTP/1.1 1615 ``` 1616 1617 #### Response 1618 1619 ```http 1620 HTTP/1.1 204 No Content 1621 ``` 1622 1623 1624 ## Trash 1625 1626 When a file is deleted, it is first moved to the trash. In the trash, it can be 1627 restored. Or, after some time, it will be removed from the trash and permanently 1628 destroyed. 1629 1630 The file `trashed` attribute will be set to true. 1631 1632 ### GET /files/trash 1633 1634 List the files inside the trash. It's paginated. 1635 1636 ### Query-String 1637 1638 | Parameter | Description | 1639 | ------------ | ------------------------------------- | 1640 | page[cursor] | the last id of the results | 1641 | page[limit] | the number of entries (30 by default) | 1642 1643 #### Request 1644 1645 ```http 1646 GET /files/trash HTTP/1.1 1647 Accept: application/vnd.api+json 1648 ``` 1649 1650 #### Response 1651 1652 ```http 1653 HTTP/1.1 200 OK 1654 Content-Type: application/vnd.api+json 1655 ``` 1656 1657 ```json 1658 { 1659 "data": [ 1660 { 1661 "type": "io.cozy.files", 1662 "id": "df24aac0-7f3d-11e6-81c0-d38812bfa0a8", 1663 "meta": { 1664 "rev": "1-3b75377c" 1665 }, 1666 "attributes": { 1667 "type": "file", 1668 "dir_id": "io.cozy.files.trash-dir", 1669 "name": "foo.txt", 1670 "trashed": true, 1671 "restore_path": "/previous_parent", 1672 "md5sum": "YjAxMzQxZTc4MDNjODAwYwo=", 1673 "created_at": "2016-09-19T12:38:04Z", 1674 "updated_at": "2016-09-19T12:38:04Z", 1675 "tags": [], 1676 "size": 123, 1677 "executable": false, 1678 "class": "document", 1679 "mime": "text/plain", 1680 "cozyMetadata": { 1681 "doctypeVersion": "1", 1682 "metadataVersion": 1, 1683 "createdAt": "2016-09-20T18:32:49Z", 1684 "createdByApp": "drive", 1685 "createdOn": "https://cozy.example.com/", 1686 "updatedAt": "2016-09-20T18:32:49Z", 1687 "uploadedAt": "2016-09-20T18:32:49Z", 1688 "uploadedOn": "https://cozy.example.com/", 1689 "uploadedBy": { 1690 "slug": "drive" 1691 } 1692 } 1693 }, 1694 "links": { 1695 "self": "/files/trash/df24aac0-7f3d-11e6-81c0-d38812bfa0a8" 1696 } 1697 }, 1698 { 1699 "type": "io.cozy.files", 1700 "id": "4a4fc582-7f3e-11e6-b9ca-278406b6ddd4", 1701 "meta": { 1702 "rev": "1-4a09030e" 1703 }, 1704 "attributes": { 1705 "type": "file", 1706 "dir_id": "io.cozy.files.trash-dir", 1707 "name": "bar.txt", 1708 "trashed": true, 1709 "restore_path": "/other_parent", 1710 "md5sum": "YWVhYjg3ZWI0OWQzZjRlMAo=", 1711 "created_at": "2016-09-19T12:38:04Z", 1712 "updated_at": "2016-09-19T12:38:04Z", 1713 "tags": [], 1714 "size": 456, 1715 "executable": false, 1716 "class": "document", 1717 "mime": "text/plain", 1718 "cozyMetadata": { 1719 "doctypeVersion": "1", 1720 "metadataVersion": 1, 1721 "createdAt": "2016-09-20T18:32:49Z", 1722 "createdByApp": "drive", 1723 "createdOn": "https://cozy.example.com/", 1724 "updatedAt": "2016-09-20T18:32:49Z", 1725 "uploadedAt": "2016-09-20T18:32:49Z", 1726 "uploadedOn": "https://cozy.example.com/", 1727 "uploadedBy": { 1728 "slug": "drive" 1729 } 1730 } 1731 }, 1732 "links": { 1733 "self": "/files/trash/4a4fc582-7f3e-11e6-b9ca-278406b6ddd4" 1734 } 1735 } 1736 ] 1737 } 1738 ``` 1739 1740 ### POST /files/trash/:file-id 1741 1742 Restore the file with the `file-id` identifiant into its `restore_path`. If a file already exists at the restore path with the same name, a suffix will be added to avoid any conflict. 1743 1744 The file's `trashed` attributes will be set to false. 1745 1746 ### DELETE /files/trash/:file-id 1747 1748 Destroy the file and make it unrecoverable (it will still be available in 1749 backups). 1750 1751 ### DELETE /files/trash 1752 1753 Clear out the trash. 1754 1755 ## Trashed attribute 1756 1757 All files that are inside the trash will have a `trashed: true` attribute. This 1758 attribute can be used in mango queries to only get "interesting" files. 1759 1760 ## Real-time via websockets 1761 1762 In addition to the normal events for files, the stack also injects some events 1763 when a thumbnail is generated. A permission on `io.cozy.files` is required to 1764 subscribe to those events on `io.cozy.files.thumbnails`. 1765 1766 ### Example 1767 1768 ``` 1769 client > {"method": "AUTH", 1770 "payload": "xxAppOrAuthTokenxx="} 1771 client > {"method": "SUBSCRIBE", 1772 "payload": {"type": "io.cozy.files.thumbnails"}} 1773 server > {"event": "CREATED", 1774 "payload": {"id": "9152d568-7e7c-11e6-a377-37cbfb190b4b", 1775 "type": "io.cozy.files.thumbnails", 1776 "doc": {"format": "large"}}} 1777 server > {"event": "CREATED", 1778 "payload": {"id": "9152d568-7e7c-11e6-a377-37cbfb190b4b", 1779 "type": "io.cozy.files.thumbnails", 1780 "doc": {"format": "medium"}}} 1781 server > {"event": "CREATED", 1782 "payload": {"id": "9152d568-7e7c-11e6-a377-37cbfb190b4b", 1783 "type": "io.cozy.files.thumbnails", 1784 "doc": {"format": "small"}}} 1785 server > {"event": "CREATED", 1786 "payload": {"id": "9152d568-7e7c-11e6-a377-37cbfb190b4b", 1787 "type": "io.cozy.files.thumbnails", 1788 "doc": {"format": "tiny"}}} 1789 ```