Exploring the Simplenote API

I’ve been meaning to work with the Simplenote API ever since it was announced, thinking it would be a good way to keep my plain-text todo lists1 synced between my computers and my iPhone. I haven’t done any syncing yet, but I have written a utility script that will get me started.

There are, as you may know, already several ways to sync your Simplenotes. Most of them, unfortunately, are tied to special note-taking apps that I don’t want install. One, Fletcher Penney’s SimplenoteSync, is more general, but works by syncing all the notes to a set of files in a single directory on your local computer. I’m looking for something a little more fine-grained than that—a way of syncing individual notes to individual files that can be anywhere on my computer.

As a first step, I wrote the following script, simplenote-index, which gathers and prints out information for all the notes on the Simplenote server.

 1:  #!/usr/bin/python
 2:  
 3:  from urllib import urlopen        # standard Python library
 4:  from base64 import b64encode      # standard Python library
 5:  import simplejson                 # http://code.google.com/p/simplejson/
 6:  
 7:  # Login credentials.
 8:  email = 'someone@example.com'
 9:  password = 'seekret'
10:  
11:  # Get my authorization token for later calls.
12:  loginURL = 'https://simple-note.appspot.com/api/login'
13:  creds = b64encode('email=%s&password=%s' % (email, password))
14:  login = urlopen(loginURL, creds)
15:  token = login.readline().rstrip()
16:  login.close()
17:  
18:  # Get the note index.
19:  indexURL = 'https://simple-note.appspot.com/api/index?auth=%s&email=%s' % (token, email)
20:  index = urlopen(indexURL)
21:  noteList = simplejson.load(index)
22:  
23:  # Print the first line of each note along with its key.
24:  baseURL = 'https://simple-note.appspot.com/api/note?key=%s&auth=%s&email=%s'
25:  for i in noteList:
26:    noteURL = baseURL % (i['key'], token, email)
27:    title = urlopen(noteURL).readline().decode('utf-8').rstrip()[:40]
28:    print '''Title:    %s
29:  Key:      %s
30:  Modified: %s
31:  Deleted:  %s
32:  ''' % (title, i['key'], i['modify'], i['deleted'])

I think the comments explain it pretty well; there’s not much to it. It logs in, gets an authorization token, then collects the information on each of your notes on the server. Here’s the sort of output to expect:

Title:    Hardware store
Key:      agtzaW1wbGUtbm90ZXIMCxIETm90ZRiF5BsM
Modified: 2009-09-08 00:24:13
Deleted:  False

Title:    Metra Eastbound Mon-Fri
Key:      agtzaW1wbGUtbm90ZXIMCxIETm90ZRij5h4M
Modified: 2010-01-01 17:51:59
Deleted:  False

Title:    Metra Eastbound Saturday
Key:      agtzaW1wbGUtbm90ZXIMCxIETm90ZRjC3h4M
Modified: 2010-01-01 17:52:33
Deleted:  False

Title:    Metra Eastbound Sunday
Key:      agtzaW1wbGUtbm90ZXIMCxIETm90ZRi35h4M
Modified: 2010-01-01 17:52:46
Deleted:  False

Title:    Metra Westbound Mon-Fri
Key:      agtzaW1wbGUtbm90ZXIMCxIETm90ZRik5h4M
Modified: 2010-01-01 17:53:05
Deleted:  False

Title:    Metra Westbound Saturday
Key:      agtzaW1wbGUtbm90ZXIMCxIETm90ZRjL3h4M
Modified: 2010-01-01 17:53:20
Deleted:  False

Title:    Metra Westbound Sunday
Key:      agtzaW1wbGUtbm90ZXIMCxIETm90ZRjT3h4M
Modified: 2010-01-01 17:53:37
Deleted:  False

Title:    Swimming City Times 2009
Key:      agtzaW1wbGUtbm90ZXIMCxIETm90ZRiG5BsM
Modified: 2010-01-01 17:54:33
Deleted:  False

Title:    Swimming Meet Event Order
Key:      agtzaW1wbGUtbm90ZXIMCxIETm90ZRiH5BsM
Modified: 2010-01-01 17:54:59
Deleted:  False

Title:    Weight
Key:      agtzaW1wbGUtbm90ZXIMCxIETm90ZRiTii8M
Modified: 2010-01-20 12:35:52.611425
Deleted:  False

Like Simplenote itself, the script treats the first line of each note as its title (the script prints only the first 40 characters of the title so the formatting doesn’t get screwed up). The important thing for the work I intend to do later are the keys. These are character strings that uniquely identify each note and are essential for scripts that read and write notes. The goal of simplenote-index is to give me those keys so I can hard-wire them into my syncing scripts.

With lots of notes, simplenote-index will give lots of output. Grep is a great way to filter the output down to a reasonable level. For example,

simplenote-index | grep -i -A 3 metra

will give me just the notes with the local train schedule

Title:    Metra Eastbound Mon-Fri
Key:      agtzaW1wbGUtbm90ZXIMCxIETm90ZRij5h4M
Modified: 2010-01-01 17:51:59
Deleted:  False
--
Title:    Metra Eastbound Saturday
Key:      agtzaW1wbGUtbm90ZXIMCxIETm90ZRjC3h4M
Modified: 2010-01-01 17:52:33
Deleted:  False
--
Title:    Metra Eastbound Sunday
Key:      agtzaW1wbGUtbm90ZXIMCxIETm90ZRi35h4M
Modified: 2010-01-01 17:52:46
Deleted:  False
--
Title:    Metra Westbound Mon-Fri
Key:      agtzaW1wbGUtbm90ZXIMCxIETm90ZRik5h4M
Modified: 2010-01-01 17:53:05
Deleted:  False
--
Title:    Metra Westbound Saturday
Key:      agtzaW1wbGUtbm90ZXIMCxIETm90ZRjL3h4M
Modified: 2010-01-01 17:53:20
Deleted:  False
--
Title:    Metra Westbound Sunday
Key:      agtzaW1wbGUtbm90ZXIMCxIETm90ZRjT3h4M
Modified: 2010-01-01 17:53:37
Deleted:  False

The -i option to grep makes the search case-insensitive, and the -A 3 option prints not only the line containing the search string, but the three lines after it as well.

With this easy one under my belt, I can start working on the more complicated syncing scripts.


  1. No, I don’t use OmniFocus anymore. It was just too much work for the good I got out of it. I’m back to my TextMate-based LGTD system, which I’ve updated a bit and really should do a short post on.