Liverpie works as a proxy in the following way: when a connection is opened to it from FreeSWITCH (so when a call to the associated extension is made and the dialplan executes the "socket" application), Liverpie first sends a predefined set of commands to FreeSWITCH. (These are hardcoded. If you absolutely need some other sort of channel initialization, edit @initial_commands in liverpie_server.rb).

You have to write your own web-based state machine, in the language of your choice. That means that when you load the same URL of your webapp, it will change its state and reply differently, changing its state request after request, based on the POST parameters, until the thread of the state machine execution is logically finished (presumably with a hangup command). Your state machine can be a huge "case" or "switch" statement, or it can use the concept of "next_step" as my example below, or you can do it however you please.

The idea is that you can keep the machine state in the session, since Liverpie and your cookies are buddies (as opposed to on the lunch menu).

Once FreeSWITCH responds, your webapp will be called at the given URL to reset its state machine.

Then it will be called again, as the first step of the IVR.

It is then the responsability of your web application to return a YAML containing the following information:

  1. Indication of what next FreeSWITCH event will trigger the next call to the state machine webapp;
  2. A FreeSWITCH socket command, as described in the FS docs here, here and here.

Of course the YAML must be plain text, without HTML formatting or any other sort.

Here is an example of a YAML that will send a wave playback command to FreeSWITCH, and ask it to wait for an event whose name signifies that the last execution has completed:

msg: |-
  call-command: execute
  execute-app-name: playback
  execute-app-arg: ivr/8000/ivr-welcome_to_freeswitch.wav
expected_key: event_name
Here is an example of a YAML that tells FreeSWITCH to wait a bit:
msg: api sleep 20000
expected_value: api/response
expected_key: content_type

  1. Configure Liverpie. Edit config/liverpie.yml (it's a YAML file, so remember that the usual restriction apply when editing such file; for one, never use TABs or CRLF). The options are documented.
  2. You need to set up an extension in your Freeswitch dialplan. For example, in your conf/dialplan/default.xml add this:
    <!-- my ivr via liverpie -->
    <extension name="my_ivr">
      <condition field="destination_number" expression="5002">
        <action application="answer" />
        <action application="set" data="liverpie_webapp_id=my_webapp" />
        <action application="socket" data=" async full" />
    Of course, you need to replace the IP and port with whatever is configured in Liverpie (config/liverpie.yml) - ie, where your Liverpie is running.
    IMPORTANT As of 0.5, Liverpie can now speak to more than one web application. They are all configured in liverpie.yml, based on a "liverpie_webapp_id" that you set in Freeswitch, as shown above.
  3. Start your web application (has to run on the IP and port specified in liverpie.yml).
  4. Start Liverpie.
    1. to start in console: bin/liverpie [-v] (will log to console not file)
    2. to start as daemon: bin/liverpie -d[v] (will log only to file, log/liverpie.log)
    3. to stop: bin/liverpie -a stop
  5. Test your webapp in the browser; call the reset method, then call the state machine method repeatedly and make sure the state of the application changes and gives the correct YAML responses.
  6. Call the destination number (5002 in my example above) and watch your webapp log, as well as the FreeSWITCH console.


Liverpie will always maintain a hash of parameters received from FreeSWITCH and send them over to the webapp via POST, as regular HTTP parameters.

At the first request, that hash is empty; it is then MERGED (not REPLACED) with every new set of parameters received from FreeSWITCH. That means that the values will always be refreshed, but that you will have values which have persisted from previous calls.

I am not yet sure whether that merging is needed, but it seemed like it was.

DTMF codes

If you specify a webapp_dtmf_uri in your config file, then everytime Liverpie receives a DTMF event from Freeswitch, it will call that method with a parameter named "dtmf_code". The value of that parameter will be the DTMF code received by Freeswitch.

You can return a YAML command (like with the state machine runner method), or nothing at all.

Important: Even if you use the 'read' command and use channel variables in order to retrieve the pushed keys, the DTMF events will still be issued. You are free to ignore them then, or ignore them altogether by setting webapp_dtmf_uri to empty in your Liverpie config file.

Multiple webapps

As of 0.5, Liverpie can distribute calls to more than one webapp. That means that you can set up more extensions in your dialplan, for different IVRs, and have them all handled by the same Liverpie instance.

To do that, you have to give each of your webapps an id in liverpie.yml (one is provided as example) and then set the liverpie_webapp_id channel variable as described in the example above.