A RESTful API for Tomboy Note Synchronization
This page is to document ideas for a REST API to be implemented by hypothetical Tomboy online services, and consumed via a Tomboy sync add-in (and hopefully other Tomboy note clients).
(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.)
Some description of our sync interfaces: http://lists.beatniksoftware.com/pipermail/tomboy-list-beatniksoftware.com/2009-January/000979.html
Proposed Resources
Responses represented using JSON for convenience. Would expect any implementer of this API to provide XML and JSON formats.
Will probably use same authentication model as Remember The Milk and Flickr. This means that there would be an auth_token parameter included in each query that requires authentication. Other choices include Basic-over-HTTPS and OAuth, plus whatever else you can imagine.
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".
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
}
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?)
}
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
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"
}]
}
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"]
}]
}
http://domain/api/1.0/user/friends
- Supported HTTP Methods: GET
- Supported query parameters: None
- Not required for sync, obviously
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
Notes
All fields of a Note object are option, except the GUID. Let's explore the consequences of setting or not setting Note object fields:
WORK IN PROGRESS
Field |
If Included |
If Excluded |
guid |
required |
required |
ref |
ignored on PUT/POST |
ignored |
title |
Requires change to note-content |
May still be updated if title changes in note-content (?) |
note-content |
May cause title to change (?), triggers change in last-change-date if no change specified |
ignored |
note-content-version |
Updated |
required with note-content, or default to 0.1? |
last-change-date |
Triggers change in last-metadata-change-date if no change specified |
May still be updated if note-content changes |
last-metadata-change-date |
Updated |
May still be updated if last-change-date, open-on-startup, or tags change |
create-date |
Updated |
Ignored |
open-on-startup |
Updated |
Ignored |
pinned |
Updated |
Ignored |
