-
Notifications
You must be signed in to change notification settings - Fork 27
Storage
This is the interesting API. The current endpoint host is document-storage-production-dot-remarkable-production.appspot.com
, but the Service Discovery should be used to make sure that the right one is used.
All requests should be made with a Bearer authentication header. Input and Output is JSON.
The Storage API uses a JSON object to represent individual file or folder items. These items are passed to and from the calls described below. Not all of the fields are always present or needed.
The items used in the API are similar but not the same as the *.metadata files located on the reMarkable device itself.
{
"ID": "10280264-2546-4319-a150-0cd02ca69c2d",
"Version": 2,
"Message": "",
"Success": true,
"BlobURLGet": "",
"BlobURLGetExpires": "0001-01-01T00:00:00Z",
"ModifiedClient": "2018-01-24T21:02:59.624624Z",
"Type": "CollectionType",
"VissibleName": "Projects",
"CurrentPage": 0,
"Bookmarked": false,
"Parent": "6d6ad886-5d8d-4b3e-aa6f-b05d46d31e83"
}
Field | Type | Description |
---|---|---|
ID |
uuid | The unique ID of this object. UUID-4 format. This is always required! |
Version |
integer | The item's version counting starts at 1
|
Message |
string | This is used in API replies to return error messages regarding this item |
Success |
boolean | This is used in API replies to signal that an error occurred handling this item (=false) |
BlobURLGet |
string | the download URL |
BlobURLGetExpires |
datetime | when above URL expires |
BlobURLPut |
string | Where the data for the file can be uploaded |
BlobURLPutExpires |
datetime | when above URL expires |
ModifiedClient |
datetime | The last modified date time as set on the client that created the item |
Type |
type | The type of the object. See below for available types |
VissibleName |
string | The file's label. Yes, there is a typo in this key. |
CurrentPage |
integer | The currently open page, starting at 0
|
Bookmarked |
boolean | is this bookmarked? |
Parent |
uuid | The ID of the parent object or empty if this is a top level object |
The Type
is sent as string using the following values:
-
DocumentType
for Notebooks -
CollectionType
for Folders
datetimes are specified in ISO 8601 format.
Note that all calls accepting items as input, expect an array of items and will alway return a corresponding array of items. However the example PHP implementation will always pass single items (eg. arrays of a single item) to make error handling easier.
Method | Endpoint | Payload | Result |
---|---|---|---|
GET |
document-storage/json/2/docs |
none | list of items |
This call queries all folders and files available. The reMarkable Tablet stores all files in a totally flat hierarchy and so does the cloud service.
The response is an array of items in no apparent order. You will need to make sense of the hierarchy by inspecting the Parent
attribute of each item. Items with an empty Parent
attribute are located at the root level.
[{
"ID": "10280264-2546-4319-a150-0cd02ca69c2d",
"Version": 2,
"Message": "",
"Success": true,
"BlobURLGet": "",
"BlobURLGetExpires": "0001-01-01T00:00:00Z",
"ModifiedClient": "2018-01-24T21:02:59.624624Z",
"Type": "CollectionType",
"VissibleName": "Projects",
"CurrentPage": 0,
"Bookmarked": false,
"Parent": "6d6ad886-5d8d-4b3e-aa6f-b05d46d31e83"
}]
Parameter | Type | Description |
---|---|---|
doc |
UUID-4 | When this parameter is present only the given document is returned. The result is still an array! |
withBlob |
boolean | When any trueish value is passed, the results will contain a valid BlobURLGet attribute that can be used to download the document |
When you pass the withBlob
parameter, you can download the document data from the returned BlobURLGet
attribute using a simple GET request.
The data you receive is a Zip-File containing the data described in the reMarkable Wiki namely:
{id}.content
{id}.pagedata
-
{id}.lines
if there are any drawings -
{id}.pdf
if this is a document (not a notebook) -
{id}.thumbnails/*.jpg
Thumbnail files per page
There seems to be no way to download a readymade annotated PDF. You would need to create this yourself by combining the PDF and the lines file.
Method | Endpoint | Payload | Result |
---|---|---|---|
PUT |
document-storage/json/2/upload/request |
list of items | list of items |
To create a document you have to create an upload request first, then upload the actual data to the returned BlobURLPut
. Finally you need to update the metadata to make the entry visible.
You need to create the ID
(UUID-4) yourself. The uploaded file data needs to be a zip file as described in the download section. You can omit generating any thumbnails and when generating the .content
file it seems to be okay to not have a pageCount
attribute and make the transform
attribute an empty array.
Newly created elements always need to have a Version
of 1
!
The following payload creates a new document at the top level.
[{
"ID": "1dd71dfc-a463-4317-9428-ece0bff128b9",
"Type": "DocumentType",
"Version": 1
}]
The following example shows the result returned by the API. Please note that not the complete Item MetaData is returned, only the minimal data to identify the new item and the upload URL is contained.
The result contains a BlobURLPut
attribute where the actual file content (PDF format) should be sent to using the PUT
method.
[{
"ID": "1dd71dfc-a463-4317-9428-ece0bff128b9",
"Version": 1,
"Message": "",
"Success": true,
"BlobURLPut": "https://storage.googleapis.com/remarkable-production-document-storage/user-auth0%7C5a68dc51cb30df3877a1d7c4/1dd71dfc-a463-4317-9428-ece0bff128b9?Expires=1517253532\u0026GoogleAccessId=remarkable-production%40appspot.gserviceaccount.com\u0026Signature=RklnAKXYxl6%2FEDXxAj%2B0d8W8IrqymHYeNZoPXEcHTGdjc1F0%2B8jsxsYFC7AVYVYG2yHt3R3ujTaWfaV1fa%2BX1MMjdLEjzsbhDv5F5HW3dJ4OHtllwBMi7HY8pEj%2FIO2c0PkY1vhfNuRriAhhPKVMm3Y17g7vdm%2Bcli90QtIvdh%2FlHfPh8OWhlZ%2BShH5fwEzNH%2Bs5EgUoq2YVqEOzWdPUclSPQGp9PbKQwJuKw7tTynjbfQCV%2FRFrh2zDn%2BK7Pci4CVCMjZCKfFqUThTxVmPEBLHtC%2F2oKWTOL4CQ8FQPtAWIPmL65zm7iGIlmfkTzu9BRpUov86QXds6tpSFSLcAmQ%3D%3D",
"BlobURLPutExpires": "2018-01-29T19:18:52.854382809Z"
}]
Note that the request PUTing the document should either have no Content-Type
header or an empty Content-Type
header. Other headers will cause the signature check to fail, resulting in a 403 response.
After the data has been uploaded, you need to do a metadata update as described in the next section to make it visible. There you can also provide a name and last modified date.
:?: how to upload a new version of an existing file?
Method | Endpoint | Payload | Result |
---|---|---|---|
PUT |
document-storage/json/2/upload/update-status |
list of items | list of items |
This call allows you to update the metadata of an existing item. You can use this to move or rename items or to bookmark them.
This call is also used to create folders. When creating a new folder the version needs to start at 1
. Creating a folder follows the same rules as creating the metadata for a File Upload.
❓ do you need to pass a complete item? Or just the ID
and the attributes you want to change?
❓ what happens if you change the Version
?
Method | Endpoint | Payload | Result |
---|---|---|---|
PUT |
/document-storage/json/2/delete |
list of items | list of items |
This allows for deleting items. It is only needed to pass two attributes: the ID
and the Version
. The Version
needs to match the current version on the server.
❓ is it possible to access/restore earlier versions?
❓ should the actual file content be deleted as well? How?
[{
"ID": "1dd71dfc-a463-4317-9428-ece0bff128b9",
"Version": 1
}]