Hacking on OpenTable public API

An importance of having a public API for the service or platform you're working on is really critical when it comes down to integration time and effort from developer's side. Selection of tools that you can use is very wide nowadays, so it should not be a limitation, even if it comes to spending more time learning something new and cool.

Im talking about OpenTable. It is a restaurant reservation platform that available on web and mobile web. Once you get a chance to know how the actual integration works, you'll probably say wtf a bunch of times.


Basically, integration with OpenTable requires you to do a few steps to get to the point where you can access data in the way you usually do, eg. using database query from MySQL or any other database of your choice. Steps are:

  • Connect to FTP server with given credentials (available for everyone)
  • Download an excel spreadsheet. Its not a CSV file as you might think. Instead, you get to work with real XLS file. Sad, but true. There is also an updates file that contains new restaurants. Files are getting updated every week.
  • Parse XLS file in order to insert data into your database
  • Repeat every week

As you might find this easy to understand, it actually requires you to do some unusual work to get comfortable with the data instead of using regular REST api endpoint. Once you've done it you probably won't do it again (depends on the work you do) or just copy and paste the existing codebase.


Everybody loves working with API's, including me. So i decided to build an API for OpenTable one night just in one hour as a challenge. As a result, i've got unofficial OpenTable public API.


  • Ruby 1.9.2
  • Sinatra 1.3.2 (with sinatra-synchrony)
  • MongoDB + Mongoid


  • Heroku - free instance
  • MongoLab - free database upto 240 mb

Consuming API

You can use any tool of your choice, but for convenience i've build a simple wrapper using faraday. Check out this gist: https://gist.github.com/2504683.


api = OpenTable::Client.new

# Find restaurants
resp = api.restaurants(:city => "Chicago")

# Process response
resp['count']       # => records found
resp['restaurants'] # => restaurant records

# Fetch a single record