Add voice to anything!

Adding a telephone number to collect audio has never been easier. Our free public API makes it simple to get going fast. Better yet, there are NO ads!

Overview

Our developer platform is a super simple and clean RESTful API. Use our API to create a "group", think of it as a voice bucket that can hold one or many recordings. Each time someone calls your group's number and leaves an audio earfl, the mp3 is immediately available online. Create a group for anything you'd like to start collecting audio for. You can have as many as you like, go nuts!

You can find out more about our ruby gem by viewing our online documentation or by visiting our rubyforge project page.

Rails Config

Simply paste the following two lines into your environment.rb:
require 'earfl'
EARFL = Earfl::Client.new('YOUR_API_KEY', 'YOUR_API_SECRET')

Required Parameters

All API requests must contain the following parameters with valid values, as described in the table below.
Param name Description Valid Values
api_key Your application's unique api_key. See my applications for your specific value.
v API version information 'v=1.0' is the only version supported at this time.
format Responses will be returned in this format All API calls must use 'format=xml'. In the future json and other formats may be supported.
call_id An increasing number determined by the client application. Each subsequent API call made must include a call_id with a greater value than any previous call made by that client. We recommend using current time in milliseconds. For example if a call was made with call_id=123 then a valid next call_id might be call_id=124
sig All requests must be signed for authentication using MD5, as described in the next section below. Digest::MD5.hexdigest(path + sorted_param_key_value_pairs + YOUR_API_SECRET)

Authentication - Request Signing

If you're using our Ruby gem you can skip this section, otherwise if you're writing your own client, keep reading. We secure your API requests with a simple signing mechanism. All requests must contain a "sig" parameter that is created by:
Digest::MD5.hexdigest(path + sorted_param_key_value_pairs
	  + YOUR_API_SECRET)
where path might be
/groups/123
and sorted_param_key_value_pairs might be:
api_key=YOUR_API_KEYcall_id=5555format=xmlv=1.0

Assuming the above example was a GET request, after adding the hostname, the resulting url would look like:
http://api.earfl.com/groups/123?api_key=YOUR_API_KEY
	  &format=xml&call_id=5555&v=1.0&sig=MD5_RESULT_FROM_ABOVE

Managing API Resources RESTfully

Groups and Recordings are the main resources that you'll be CRUD'ing RESTfully. The HTTP verbs are as follows:
Operation HTTP method Group url Recording url
Create POST /groups /recordings
Read GET /groups/123 /recordings/123
Update PUT (or POST with _method=put parameter) /groups/123 /recordings/123
Delete DELETE (or POST with _method=delete parameter) /groups/123 /recordings/123

Success responses are of the form:
  <?xml version="1.0" encoding="UTF-8"?>
  <rsp stat="ok">
    ---PAYLOAD HERE---
  </rsp>

Error responses are of the form:
  <?xml version="1.0" encoding="UTF-8"?>
  <rsp stat="failed">
    ---PAYLOAD HERE---
  </rsp>

Here's a sample response from a GET on /group/342:
<?xml version="1.0" encoding="UTF-8"?>
<rsp stat="ok">
<group>
  <id>342</id>
  <title>Taco Bell Audio Reviews</title>
  <description>Call in your reviews for Taco Bell</description>
  <default_tags></default_tags>
  <is_private>false</is_private>
  <call_in_number>1(415)223-3804 and enter code: 342</call_in_number>
  <greeting_recording_id></greeting_recording_id>
  <featured_recording_id>146</featured_recording_id>
  <size>2</size>
  <created_at>Wed Mar 05 12:33:05 -0800 2008</created_at>
  <updated_at>Fri Mar 07 18:15:49 -0800 2008</updated_at>
  <recordings for_group="342" page="1" per_page="20">
    <recording>
      <id>146</id>
      <first_name>Matt</first_name>
      <last_name>Wilson</last_name>
      <title>Chalupafication!</title>
      <description></description>
      <size>590106</size>
      <length>63</length>
      <play_count>9</play_count>
      <avg_rating>0.0</avg_rating>
      <sound_uri>/recordings/146.mp3</sound_uri>
      <created_at>Wed Mar 05 12:41:19 -0800 2008</created_at>
      <updated_at>Wed Mar 05 12:42:47 -0800 2008</updated_at>
      <picture_uri>http://flickr.com/chalupaz.jpg</picture_uri>
    </recording>
    <recording>
      <id>86</id>
      <first_name>Matt</first_name>
      <last_name>Wilson</last_name>
      <title>Dude, where's my wookie prize?</title>
      <description>I want my 32oz wookie cup!</description>
      <size>63164</size>
      <length>0</length>
      <play_count>11</play_count>
      <avg_rating>0.0</avg_rating>
      <sound_uri>/recordings/86.mp3</sound_uri>
      <created_at>Wed Jan 09 15:23:03 -0800 2008</created_at>
      <updated_at>Tue Jan 29 12:03:12 -0800 2008</updated_at>
      <picture_uri>http://flickr.com/mywookiecup.jpg</picture_uri>
    </recording>
  </recordings>
</group>
</rsp>
An unsuccessful request might return:
  <?xml version="1.0" encoding="UTF-8"?>
  <rsp stat="failed">
    <err code="404" msg="Recording not found: 191"/>
  </rsp>

Managing your group's data using the earfl ruby gem

If you are using ruby or ruby on rails, we have a ruby gem that will help you get up and running in a snap! If you have additional questions or if you are interested in using our API with a different platform or language you can contact us through our support forum

Ruby users can use an 'irb' session to test your API key and verify that the gem is working correctly. The following code shows how to run a basic check to test your earfl gem and make sure that its API connection is working. Of course, you'll need to substitute the KEYS used in this example with your registered earfl API_KEYs

irb(main):001:0> # make sure that the gem is available/installed
irb(main):002:0> require 'earfl'
=> true
irb(main):003:0> EARFL = Earfl::Client.new('YOUR_KEY', 'YOUR_SECRET')
=>#<Earfl::Client:0xb77c82bc @api_secret="YOUR_SECRET",
    @api_key="YOUR_KEY", @host="http://www.earfl.com",
    @base_params={:format=>"xml", :api_key=>"YOUR_KEY", :v=>"1.0"}>
irb(main):004:0> EARFL.is_alive?
=> true

Next, we'll use the gem to retreive a group through the API. The earfl gem can help you create local representations of the remote objects that we are storing for you. I'll continue our previous irb session to show you some examples.

irb(main):005:0> group = EARFL.groups_read('id' => '101')
=>#<Earfl::Group:0x...  (group return value goes here) ...
irb(main):006:0> # now that we have a local copy of the remote group
irb(main):007:0> # object, now lets find its title
irb(main):008:0> group.title
=> "example_group_title"
irb(main):009:0> # Looks good. Now check how many recordings have been
irb(main):010:0> # contributed to this group so far.
irb(main):011:0> group.recordings.size
=> 5

Now we can check the title of the first recording in this group's collection and then remove that recording from the group's listing. The un_contribute operation should remove the selected recording from the group's listing and return an updated group.

irb(main):012:0> group.recordings.first.title
=> "a recording title"
irb(main):013:0> updated_group = EARFL.groups_uncontribute('id' =>
    group.id, 'recording_id' => group.recordings.first.id )
=>#<Earfl::Group:0x...  (updated_group return value goes here) ...
irb(main):014:0> # check the number of recordings in our updated group
irb(main):014:0> # and make sure everything worked.
irb(main):015:0> updated_group.recordings.size
=> 4

You can also customize your IVR by setting your group's greeting_recording_id or farewell_recording_id respectively. Note: update operations require that the attributes are fully qualified with 'group[ATTRIBUTE_TO_BE_UPDATED]' as shown below. i.e. when updating recordings or other resources you need to provide parameter names of the form 'recording[ATTRIBUTE_TO_BE_UPDATED]' etc...

>> group = EARFL.groups_read('id' => '166')
>> group.greeting_recording_id
=> {}
>> updated_group = EARFL.groups_update('id' => '166',
    'group[greeting_recording_id]' => '2725')
>> updated_group.greeting_recording_id
=> "2725"

Error Responses

All error response codes can be found both in the HTTP header as well as in the payload as seen above.

The list of possible error codes is:

400: Resource Invalid (improperly formatted request)
401: Unauthorized (incorrect or missing sig parameter)
403: Forbidden (trying to modify a recording or group that isn't yours)
404: Resource Not Found
415: Unsupported Media Type (bad format for recording upload and/or bad format requested e.g. /recordings/123.flac)
500: Internal Server Error