Tomboy Web, A RESTful API for Tomboy Note Synchronization
This is the documentation of the REST API used by Tomboy, Tomdroid, and Conboy to perform web synchronization with Snowy, Ubuntu One, and Midgard2. It has not been finalized, but since a Tomboy Web sync add-in shipped in Tomboy 1.0, any updates must keep backwards compatibility in mind.
Contents
Proposed additions to the spec are italicized.
(A note about REST: As Tomboy notes are interconnected, CRUD of individual note resources has a lot of implications and is not initially supported. The method for updating notes on the server breaks a few REST principles, but is still pretty clean.)
Tomboy's synchronization algorithm is in the process of being documented.
Resources
Responses represented using JSON for convenience. Would expect any implementer of this API to provide XML and JSON formats.
Current spec requires use of OAuth for authentication.
URIs include "api" , so that you can, for example, visit http://domain/sally/notes/123/new-note-6 and get a pretty interactive web page, then visit http://domain/api/1.0/sally/notes/123 to get the JSON/XML/whatever response. Response format could probably be specified with format query parameter with choices of "xml" or "json".
Another very important note about these URLs: although the spec refers to URLs like api/1.0/user/notes, this exact URL is not required. The only exact URL that is required is api/1.0. When authenticated, that URL will provide a user-ref containing another API URL (which may or may not be api/1.0/user), and the user URL will provide a notes-ref containing yet another API URL (which may or may not be api/1.0/user/notes). Clients of this API must take this into account when developing support for this REST API. Of note, Ubuntu One does not use the exact URLs listed here for users and notes.
1. http://domain/api/1.0
- Supported HTTP Methods: GET
- Supported query parameters: None
Response example: http://domain/api/1.0
{ "user-ref": { "api-ref" : "http://domain/api/1.0/sally", "href" : "http://domain/sally" }, "oauth_request_token_url": "http://domain/oauth/request_token", "oauth_authorize_url": "http://domain/oauth/authorize", "oauth_access_token_url": "http://domain/oauth/access_token", "api-version": 1.0 }
2. http://domain/api/1.0/user
- Supported HTTP Methods: GET
- Supported query parameters: None
Response example: http://domain/api/1.0/sally
{ "user-name": "sally", "first-name": "sally", "last-name": "walters", "notes-ref": { "api-ref" : "http://domain/api/1.0/sally/notes", "href" : "http://domain/sally/notes" }, "friends-ref": { "api-ref" : "http://domain/api/1.0/sally/friends", }, "latest-sync-revision": 456 (maybe you only get this number if the user is you?), "current-sync-guid": "ff2e91b2-1234-4eab-3000-abcde49a7705" (maybe you only get this number if the user is you?) }
3. http://domain/api/1.0/user/notes
- Supported HTTP Methods: GET, PUT
- A PUT lets you update/add/delete notes in the collection
- Supported query parameters:
since - an integer specifying a sync revision number
include_notes - a boolean defaulting to False indicating whether or not full note data should be included (I wish I had called this include_content instead. Maybe in a future update to this API we will add include_content as an alias for include_notes, and recommend it instead for clarity)
content_version - (seems like a good idea?) ability for old clients to continue requesting note data in old content versions (assuming transformation is possible and desirable)
Response example: GET http://domain/api/1.0/sally/notes
{ "latest-sync-revision": 456, "notes": [{ "guid": "002e91a2-2e34-4e2d-bf88-21def49a7705", "ref": { "api-ref": "http://domain/api/1.0/sally/notes/123", "href": "http://domain/sally/notes/123/new-note-6" }, "title": "New Note 6" }, { ...(another one)... }] }
Response example: GET http://domain/api/1.0/sally/notes?include_notes=true
{ "latest-sync-revision": 456, "notes": [{ "guid": "002e91a2-2e34-4e2d-bf88-21def49a7705", "title": "New Note 6", "note-content": "Describe your note <b>here</b>.", "note-content-version": 0.1, "last-change-date": "2009-04-19T21:29:23.2197340-07:00", "last-metadata-change-date": "2009-04-19T21:29:23.2197340-07:00", "create-date": "2008-03-06T13:44:46.4342680-08:00", "last-sync-revision": 57, "open-on-startup": false, "pinned": false, "tags": ["tag1", "tag2", "tag3", "system:notebook:biology"] }, { ...(another one)... }] }
Request example: PUT http://domain/api/1.0/sally/notes (response should be the full listing from http://domain/api/1.0/sally/notes )
{ "latest-sync-revision": 456, "note-changes": [{ "guid": "002e91a2-2e34-4e2d-bf88-21def49a7705", "title": "New Note 6", "note-content": "Describe your note <b>here</b>.", "note-content-version": 0.1, "last-change-date": "2009-04-19T21:29:23.2197340-07:00", "last-metadata-change-date": "2009-04-19T21:29:23.2197340-07:00", "create-date": "2008-03-06T13:44:46.4342680-08:00", "open-on-startup": false, "pinned": false, "tags": ["tag1", "tag2", "tag3", "system:notebook:biology"] }, { ...(another one)... }, { "guid": "0bc7b1ef-264f-4aa9-8746-d0f87e9b0176", "command": "delete" }] }
4. http://domain/api/1.0/user/notes/id
- Supported HTTP Methods: GET
- Supported query parameters:
content_version - (seems like a good idea?) ability for old clients to continue requesting note data in old content versions (assuming transformation is possible and desirable)
- Not required for sync
Response example: GET http://domain/api/1.0/sally/notes/123 (Consider dropping "note", also redundant array notation)
{ "note": [{ "guid": "002e91a2-2e34-4e2d-bf88-21def49a7705", "title": "New Note 6", "note-content": "Describe your note <b>here</b>.", "note-content-version": 0.1, "last-change-date": "2009-04-19T21:29:23.2197340-07:00", "last-metadata-change-date": "2009-04-19T21:29:23.2197340-07:00", "create-date": "2008-03-06T13:44:46.4342680-08:00", "open-on-startup": false, "pinned": false, "tags": ["tag1", "tag2", "tag3", "system:notebook:biology"] }] }
5. http://domain/api/1.0/user/friends
Supported HTTP Methods: GET
Supported query parameters: None
- Not required for sync, obviously
Currently not supported by any existing server implementation, or used by any client implementation
Response example: GET http://domain/api/1.0/sally/friends
{ "friends":[{ "name": "sally walters", "ref": { "api-ref": "http://domain/api/1.0/sally", "href": "http://domain/sally" } }, { "name": "jonathan", "ref": { "api-ref": "http://domain/api/1.0/jonny5", "href": "http://domain/jonny5" } }] }
Things to Consider When PUT/POSTing Resources
1. Notes
All fields of a Note object are optional, except the GUID. Let's explore the consequences of setting or not setting Note object fields:
Field |
If Included |
If Excluded |
guid |
Required |
Required |
ref |
Ignored on PUT/POST |
Ignored |
title |
Updated |
Ignored |
note-content |
Updated |
Ignored |
note-content-version |
Updated |
Required with note-content, or default to 0.1? |
last-change-date |
Updated |
Ignored (though maybe it should be updated to current datetimestamp if title or content are modified?) |
last-metadata-change-date |
Updated |
Updated to current datetimestamp |
create-date |
Updated |
Ignored |
open-on-startup |
Updated |
Ignored |
pinned |
Updated |
Ignored |
tags |
Updated (previous tags overwritten with newly-specified tags) |
Ignored |
command |
If set to 'delete', note will be deleted; otherwise, ignored |
Ignored |