For a long time I have used hand written to-do lists as a form of daily task tracking. As task management software has gotten better, the inconvenience of the paper list (copying it, losing it, etc.) has made even a luddite like myself ditch it. I have been using Trello for a few years now and it’s been great. However every time I have to futz with my phone to update the list, I long for the good ol’ days when I could mark my progress with the swift and satisfying swipe of a sharpie. After hearing about the Memobird printer, I figured I could maybe use it to automatically print out my To-do list everyday, so I’d have the best of both worlds.

It turns out the Memobird’s API is still in a private beta for now, but they do have an IFTTT service. This, plus a few other automation tools, is all we need to make this happen. I’ve included instructions below in case other Memobird owners want to give something like this a shot. Here’s what I did:

  • Set up an IFTTT applet with a webhook that prints the payload on the Memobird
  • Wrote an AWS Lambda endpoint to pull my to-do list from Trello, format it, and send it to this webhook
  • Set up a Zapier “zap” to spin up the Lambda endpoint every day at 8am

IFTTT configuration

  • Create a new applet and add “Webhooks” as the “this” step
  • There should only be one option for trigger, “Receive a web request”
  • You then just set the event name to whatever you like, I chose todo_print (anything in snake case is fine)
  • Set the “that” step to “Print a message to a memobird service”, using the 16-digit hex code ID for your device as the argument for the “Which memobird device?” parameter. You can press the button on the printer twice to print out this ID if you don’t have it handy
  • Set the “What message to print?” parameter to {{OccurredAt}} {{Value1}}
  • Look up your key and URL here, where your key is in your URL after use/

You can then test this on your printer with a simple curl command,:

curl -X POST "https://maker.ifttt.com/trigger/todo_print/with/key/{your key}?value1=<html><body><br>test+test2</body></html>"

AWS Lambda

So it’s entirely possible to set this up using just Zapier and IFTTT, if you use a multistep zap on Zapier and their Trello integration. However, you need to buy the paid tier and it starts at $250 a year, hence Lambda. I took a quick look at the limits on the AWS free tier and unless you had a very long to-do list, it’s nigh impossible to exceed them with this simple function.

  • Create a new AWS Lambda function here
  • After you click create, you’ll choose “Author from scratch”
  • Select a name (“getTodoListAndPost”), set the runtime to Python 2, and create a new role with the template “Simple microservice permissions”

You’ll also need to grab some info from Trello so you can point your Lambda function to the right list:

  • Look up the list ID on Trello (go to board, menu, more, print and export, export as json)

  • In the json, search for “Today” or whatever your “Doing” list is called and copy the adjacent ID

  • Get a key from the Trello API here, and then click through to get a token. You’ll have to grant “Server Token” permissions on your Trello account to do so)
  • Add your list ID, your key-token pair for trello, and your key for the maker API to the environment variables on Lambda
  • Add the code below (download the file here) in your lambda_handler
  • Test, using any input ( I used the “Hello World!” sample event). This should print your to-do list on the printer successfully at this point
  • Publish your Lambda function
import os
import json
from botocore.vendored import requests

def lambda_handler(event, context):

    # you should probably reduce this in your code, but this was just broken down for readability
    full_url = "https://api.trello.com/1/lists/" + os.environ.get('list_id') + "/cards?fields=id,name"
    full_url = full_url + "&key=" + os.environ.get('trello_key')
    full_url = full_url + "&token=" + os.environ.get('trello_token')
    response = requests.get(full_url)

    cards = response.json()
    names = []
    for card in cards:
        names.append(card["name"])
    output= {}
    output["value1"] = "<html><body><br><ul><li>" + "</li><li>".join(names) + "</li></ul></body></html>"

    # send to the printer's ifttt hook
    printer_result = requests.post("https://maker.ifttt.com/trigger/todo_ready/with/key/" + os.environ.get('maker_key'), data = output)

    # So, you obviously should be doing some error handling here, but for a small
    # personal project like this, I'd rather cross that bridge when I get to it
    return {
        'statusCode': 200,
        'body': str(printer_result),
    }

So now that you have your Lambda function all set up, you need to set up a way to tell it when to execute. We’ll use an API Gateway to do this.

  • On the page where you added the code to your Lambda function, click on “API Gateway” under “Triggers” to begin API Gateway setup

I’ve shown my settings here configured, but you might need to create the API endpoint, which should be straightforward enough.

  • Test your API gateway trigger with a curl command e.g.
curl -X GET "https://ijmtjfn8f0.execute-api.us-west-2.amazonaws.com/default/getTodolistAndSendToIFTTT?key=f****************************"

You can get the URL from the Lambda interface:

Adding the chron job to Zapier

Once Lambda is set up, you can just create a simple Zap in Zapier to hit it everyday. You might be wondering, couldn’t I also do this in IFTTT? The answer is, of course, but I’ve found Zapier to be a bit more reliable than IFTTT and has better error messages.

  • Create a new Zap whose trigger is “Schedule”, and select “Every Day” and the time you wake up
  • Add the action “POST” from “Webhooks by Zapier”
  • Add the URL you tested in the last step, with your API key from your API Gateway configuration

One last tip

I try to keep the habit of writing my daily to-do list the night before, but sometimes I forget to update it and I want to make some edits after it prints. I just have the curl command above saved on my desktop and I can reprint by quickly re-running that command.