reMarkable-cloud-js
reMarkable Cloud API for NodeJS
Inspired by
- Alexander Keil's unofficial reMarkable Cloud API documentation
- jmptable's ReMarkable Tablet Cloud API
- ogdentrod's reMarkable-typescript
Features
- [X] Authentication
- [X] device registration
- [X] user connection
- [X] data retrieval/push
- [X] files metadata retrieval
- [X] folders tree retrieval
- [X] path exists
- [X] unlink path
- [X] create directory
- [X] move path
- [X] rename path
- [X] read/write zip
- [X] copy path
- [X] read/write pdf
- [X] read/write ePub
- [X] write from url
- [X] cloud live notifications
- [X] main data feed (all updates)
- [X] subscription data feed (specific file/folder updates)
Main usage
First time authentication
const RmCJS = require('remarkable-cloud-js')
let rm_api = new RmCJS()
let device_token = await rm_api.register_device('< one time code >', RmCJS.device_desc.desktop.linux)
// save the device_token to be reused later
await rm_api.refresh_token() // auto authentication once registration is done
Common connection
const RmCJS = require('remarkable-cloud-js')
// using the saved device token + refreshing the user token
let rm_api = new RmCJS('< device token >')
await rm_api.refresh_token()
Sample storage usage
const RmCJS = require('remarkable-cloud-js')
let rm_api = new RmCJS('< device token >')
await rm_api.refresh_token()
if(!(await rm_api.exists('/My projects/blueprints'))) {
await rm_api.mkdir('/My projects/blueprints')
}
let blueprints = await rm_api.get_path_content('/My projects/Articles')
for(let blueprint of blueprints) {
if(blueprint.VissibleName.includes('to delete')) {
await rm_api.delete(blueprint._path)
}
}
await rm.write_pdf('/My projects/Articles/a really cool pdf', './pdfs/article.pdf')
Sample notifications usage
const RmCJS = require('remarkable-cloud-js')
let rm_api = new RmCJS('< device token >')
await rm_api.refresh_token()
function notification_handler(event) {
console.log('update on', event.document.VissibleName)
}
// ---- event matcher making sure all recieved event come from the remarkable tablet
let notification_matcher = {
sourceDeviceDesc: 'remarkable'
}
await rm_api.subscribe_to_notifications(notification_handler, notification_matcher)
Specifications
Device types
To use on registration
- desktop
- windows (
desktop-windows
) - macos (
desktop-macos
) - linux (
desktop-linux
)
- windows (
- mobile
- android (
mobile-android
) - ios (
mobile-ios
)
- android (
- browser
- chrome (
browser-chrome
)
- chrome (
found here
const RmCJS = require('remarkable-cloud-js')
RmCJS.device_desc
RmCJS.device_desc.desktop
RmCJS.device_desc.desktop.windows
RmCJS.device_desc.desktop.macos
RmCJS.device_desc.desktop.linux
RmCJS.device_desc.mobile
RmCJS.device_desc.mobile.android
RmCJS.device_desc.mobile.ios
RmCJS.device_desc.browser
RmCJS.device_desc.browser.chrome
ZIP MAP data representation
In the reMarkable case, ZIP data representing file content often uses the document's ID as a path component. As it is (most of the time) impossible to know this ID in advance, we propose the following zip data representation to use in some APIs arguments:
- the ZIP MAP object is reprenseted by a flat JSON object.
- each property represents a path.
- a path containing the ID uses the
{ID}
string to indicate its position in the path
- a path containing the ID uses the
- each value can be either a
string
, abuffer
or aJSON object
ZIP MAP sample
const fs = require('fs')
let pdf_zip_map = {
'{ID}.content': {
extraMetadata: {},
fileType: file_type,
lastOpenedPage: 0,
lineHeight: -1,
margins: 180,
pageCount: 0,
textScale: 1,
transform: {}
},
'{ID}.pagedata': [],
'{ID}.pdf': fs.readFileSync('< pdf file path >')
}
Document path
The reMarkable document path are absolute and starts with the root folder /
- Sample folder:
/My project/blueprint
- Sample document:
/My project/blueprint/project one
Note that no extension are used in the reMarkable filesystem
Document types
- document type (
DocumentType
) represent a "file" (notebook, pdf, epub, etc.) - collection type (
CollectionType
) represent a "folder"
found here
const RmCJS = require('remarkable-cloud-js')
RmCJS.type
RmCJS.type.document
RmCJS.type.collection
Document representation
(extended from the standard reMarkable representation)
{
ID: '< document UUID >',
Version: 1,
Message: '',
Success: true,
BlobURLGet: '',
BlobURLGetExpires: '0001-01-01T00:00:00Z',
ModifiedClient: '< last modification date string >',
Type: '< document type >',
VissibleName: '< document name >',
CurrentPage: 0,
Bookmarked: false,
Parent: '< document parent UUID >',
_path: '< detected absolute path >'
}
Standard reMarkable Document representation
The "un-extended document representation" lacks the _path
component
Notification event types
- document added (
DocAdded
) when a document is added, updated (its content) or moved (including to the trash) - document deleted (
DocDeleted
) when a document is removed from the cloud (not only trashed)
found here
const RmCJS = require('remarkable-cloud-js')
RmCJS.notification.event
RmCJS.notification.event.document_added
RmCJS.notification.event.document_deleted
Notification event data representation
found here
{
auth0UserID: '< unknown data >',
bookmarked: false,
event: '< event types >',
id: '< updating Document UUID >',
parent: '< updating Document parent UUID >',
sourceDeviceDesc: '< source device description >',
sourceDeviceID: '< source device id >',
type: '< updating Document type >',
version: '1',
vissibleName: '< updating Document name >',
publish_time: '< event occuring time string >',
document: /* Document representation if event = DocAdded */
}
Exceptions
-
path_not_found
occurs if a required path cannot be found -
update_error
occurs if an error is thrown while updating a document -
upload_request_error
occurs if an error is thrown while uploading a document -
delete_error
occurs if an error is thrown while deleting a document -
path_already_exists_error
occurs if trying to create a path already existing
API
Basic data manipulation
exists (path)
-
arguments
-
path
the path to check
-
-
output Boolean value
true
orfalse
unlink (path)
-
arguments
-
path
the path to trash
-
-
output Boolean value
true
orfalse
move (from_path, to_parent)
rename (path, new_name)
File content
write_zip (path, zip_map, type)
-
arguments
-
path
the document's path for data writing (can be existing or not) -
zip_map
the ZIP MAP data -
type
the document type
-
- output Document
read_zip (path)
mkdir (path)
copy (from_path, to_path)
- arguments
- output The copied (Document)
Specific file content
write_pdf (path, pdf_path, metadata)
-
arguments
-
path
newly added document's path -
pdf_path
the local PDF file path -
metadata
(optional,default = {}
) metadata properties to add to the default PDF file's metadata
-
- output Document
write_pdf_from_url (path, pdf_url, metadata)
-
arguments
-
path
newly added document's path -
pdf_url
the remote PDF file URL -
metadata
(optional,default = {}
) metadata properties to add to the default PDF file's metadata
-
- output Document
read_pdf (path)
write_epub (path, epub_path, metadata)
-
arguments
-
path
newly added document's path -
epub_path
the local ePub file path -
metadata
(optional,default = {}
) metadata properties to add to the default ePub file's metadata
-
- output Document
write_epub_from_url (path, epub_url, metadata)
-
arguments
-
path
newly added document's path -
epub_url
the remote ePub file URL -
metadata
(optional,default = {}
) metadata properties to add to the default ePub file's metadata
-
- output Document
read_epub (path)
Notification API
subscribe_to_notifications (handler, matching_properties)
-
arguments
-
handler
callback function on which to pass the event data -
matching_properties
subscription properties (event object propeties to filter the incoming events)
-
-
output Boolean value
true
Augmented reMarkable API
docs_paths ()
- output Document array
get_final_path (path)
this method verifies that the path exists
get_ID (id)
-
arguments
-
id
the existing document's UUID
-
- output Document
get_name (name)
-
arguments
-
name
the existing document's name
-
- output Document
get_path_content (path)
corrupted_docs ()
- output Parent missing Document array
trashed_docs ()
- output Document array
upload_zip_data (name, parent_path, type, zip_map [, doc])
- arguments
- output Document
base reMarkable API
raw_docs ()
- output reMarkable Document array
get_doc (ID [,with_blob])
-
arguments
-
ID
document's UUID -
with_blob
(optional,default = true
) indicated if the document should come with it's blob dowloading links
-
- output reMarkable Document
upload_request ([doc])
-
arguments
-
doc
(optional,default = null
) a pre-existing reMarkable Document
-
-
output fetch json response container this (among others)
ID
andBlobURLPut
update_status (doc, changed_doc_data)
-
arguments
-
doc
base reMarkable Document data containing at minimum theID
andVersion
-
- output the updating sent reMarkable Document
delete (doc)
-
arguments
-
doc
deleting reMarkable Document
-
-
output Boolean value
true
orfalse
Limitations
Cloud functionalities are not 100% reliable on the tablet and the application, it is thus recommended to use the cloud api with care and if possible with the tablet turned on and connected.