This document outlines the specifications for the client-server communications of the Standard Notes client/server system.
The protocol consists of models on the server side and what are known as structures on the client side.
Item model has a
content field. The
content field stores a JSON encoded object that can be any thing the client needs to operate. In this client-server model, servers are to be treated as dumb and uninformed.
Relationships are handled by the client and not the server, which clients today have no problem handling. This allows for improvements to be made to the data model on the client level, and not on the difficult-to-change server level. It also allows for relationships to be encrypted.
A user model has the following properties:
|String||The email of the user.|
|password||String||The password for this user. Note that passwords must be manipulated before being sent to the server.|
|pw_cost||String||The number of iterations to use for the KDF. See Encryption for more.|
|pw_nonce||String||Generated by the client during registration. See Encryption for more.|
|version||String||The version of the SF specification used when creating this user's account. (Latest is 003) (This value is also updated when a user changes their password or updates their security version.)|
Item models have the following properties:
|uuid||String (or uuid for some databases)||The unique identifier for this model.|
|content||Text||The JSON encoded structure of the item, encrypted.|
|content_type||String||The type of the structure contained in the |
|enc_item_key||Text||The locally encrypted encryption key for this item.|
|deleted||Bool||Whether the model has been deleted.|
|created_at||Date||The date this item was created.|
|updated_at||Date||The date this item was modified.|
Client structures are stored in the
content field of the
Item model. A client structure can have any property the client chooses, as well as the following:
|appData||Dictionary||A domain based dictionary whose content must be preserved between platforms. |
|references||Array||A metadata array of other |
references array sample:
All requests after the initial authentication should be authenticated with a JWT with the
Authorizationheader:Authorization: Bearer _insert_JWT_here_
Standard Notes uses JSON Web Tokens (JWT) for authentication.
Registers a user and returns a JWT
Params: email, password, pw_cost, pw_nonce, version
password needs to be processed locally before being sent to the server. See Encryption for more. Never send the user's inputted password to the server.
Updates a user's password.
Params: email, password, current_password
Authenticates a user and returns a JWT.
Note: Passwords needs to be processed locally before being sent to the server. See Encryption for more. Never send the user's inputted password to the server.
Params: email, password
Returns the parameters used for password generation.
Saves local changes as well as retrieves remote changes.
items: An array of items
sync_token: the sync token returned from the previous sync call. Leave empty if first sync.
limit: (optional) the number of results to return.
cursor_tokenis returned if more results are available.
- Clients: set
trueand sync. When receiving an item that is
deleted, remove it from the local database immediately.
- Servers: if syncing an item that is
deleted, clear out its
deletedto true, and save.
Upon sync completion, the client should handle each response item as follows:
retrieved_items: these items are new or have been modified since last sync and should be merged or created locally.
saved_items: saved items are dirty items that were sent to the sync request. These items should not be merged in their entirety upon completion. Instead, only their metadata should be merged. For example, if at Point A the client syncs a Note item that a user is still typing, and at Point B the sync completes, the user could have typed more content in between A and B. Thus, if you merge all content, the user's progress in between A and B will be lost. However, if you merge just the metadata (usually just updated_at date), then this issue is avoided.
unsaved: returned if an error occurred saving those items. This can happen in the case of a sync conflict, where an item attempting to be saved already has a pending change. This item will not be saved, and will instead be returned in this array. The client is then responsible for duplicating this item and assigning it a new UUID. Another scenario for unsaved is the improbable case of a UUID conflict.
sync_token: this token should be saved when it is received and sent to subsequent sync requests. This token should also be persisted locally between app sessions. For first time sync, no token should be provided.
cursor_token: returned if original request had a
limit. Send this token back to the server to retrieve next page of results.
The export file is a JSON file of all the user's items, unencrypted.
Join the Slack group to discuss implementation details and ask any questions you may have.
You can also email firstname.lastname@example.org.
Follow @standardnotes on Twitter for updates and announcements.