Use Twilio and your phone to make audioblog posts

Posted by techstonia on March 6, 2015

This post was featured on PyCoders Weekly #157.

Recently I played with Twilio API. Their service is mind-blowingly simple - it took me about 50 lines of Python code to set up a MVP. No, I’m not going to start a Twitter-meets-audio kind of startup - you can steal the idea. Basically I just have to call a specific number, tell my message and the audio goes to my website. You can find the humblingly minimal audioblogging platform here:

##Okay, how can I get this to work? The shortest way is to follow the instructions on my Github repository, which I’m copying here as well.

  1. Create a free Twilio account and buy a voice number.
  2. Clone this repository.
  3. Change AUTH_TOKEN and ACCOUNT_SID in You can find them under your account settings
  4. Create a Heroku app and push your code into the app. If you’re not familiar with Heroku I suggest starting here.
  5. Change the request url in your manage number page. This should be in the form of
  6. Call the number in manage number to record your first post.
  7. Yay! You have a voice blog!

P.S. Twilio service is not free, but there is an initial 30$ credit, which should be enough for playing with their service. You can also delete posts from Twilio website.

What’s under the hood?

It’s built with Flask and Bootstrap and all the logic is in When we call our magic number Twilio accesses the and get’s instructions in TwiML, which is a Twilio’s markup language. Basically the view checks if the call is made from your number and after you have pressed 1, the is accessed.

@app.route("/new", methods=['GET', 'POST'])
def new_post():
from_number = request.values.get('From', None)
resp = twilio.twiml.Response()

if from_number == MY_NR:
with resp.gather(numDigits=1, action="/handle-key", method="POST") as g:
g.say("To record a post, press 1.")
return str(resp)
resp.say("Go away intruder!")
return str(resp)

In handle-key Twilio gets instructions of what to say to you and what to do after the call has finished.

@app.route("/handle-key", methods=['GET', 'POST'])
def handle_key():
digit_pressed = request.values.get('Digits', None)
if digit_pressed == "1":
resp = twilio.twiml.Response()
resp.say("Record your post after the tone.")
resp.record(maxLength="10", action="/handle-recording")
return str(resp)
return redirect("/new")

If your call reaches 10 seconds, you’re redirected to /handle-recording, and informed that your post is now live.

@app.route("/handle-recording", methods=['GET', 'POST'])
def handle_recording():
resp = twilio.twiml.Response()
resp.say("Your post is now live! Goodbye")
return str(resp)

Now we only need a view for displaying the posts:

def index():
client = TwilioRestClient(ACCOUNT_SID, AUTH_TOKEN)
recordings = client.recordings.list()
return render_template('index.html', posts=recordings)

It’s very straightforward - we fetch recordings and pass them into render_template function, which then produces the necessary html for displaying all the posts we have created. So that’s that. Simple, huh?

Get an email whenever I publish a new post - no bullshit ever
or follow me on Twitter - @techstonia