APIdaze2015-04-13T20:24:52+00:00http://developers.apidaze.ioPhilippe SultanRoute your Voxbone numbers to your ExternalScript2014-03-01T00:00:00+00:00http://developers.apidaze.io/2014/03/01/Route-your-Voxbone-number-to-your-ExternalScript<p>Any SIP trunk can connect to APIdaze to have your incoming calls processed by your ExternalScript. This post shows how you can connect Voxbone numbers to APIdaze.</p>
<blockquote>
<p>Voxbone is an international DID numbers provider that interfaces with SIP.</p>
</blockquote>
<h2>From your Voxbone management interface</h2>
<p>Select <code>Configure</code> -> <code>URIs</code> -> <code>All URIs</code>. Then fill in the following fields in the web form :</p>
<ul>
<li>URI : {E164}@94.23.249.192 (mandatory)</li>
<li>Description : BYOT APIdaze (optional)</li>
</ul>
<p>Then save and proceed with attaching the newly created URI to the numbers your want to route to APIdaze.</p>
<p>Select <code>Configure</code> -> <code>Numbers</code>, pick the numbers and choose the <code>BYOT APIdaze</code> URI under the <code>Voice URI</code> tab. Click <code>apply to selected</code> to confirm. </p>
<p>You have now attached your Voxbone numbers to APIdaze, let's now register the numbers at APIdaze.</p>
<h2>APIdaze</h2>
<p>From the <a href="https://developers.apidaze.io">developer's portal</a> in the <code>API Reference</code> section, select <code>External Number Create (BYOT)</code> and just enter each number you routed to APIdaze from Voxbone.</p>
<p>That's it ! Your numbers are now routed and managed by your ExternalScript.</p>
Answer incoming calls from your browser with WebRTC2014-02-20T00:00:00+00:00http://developers.apidaze.io/2014/02/20/Answer-incoming-calls-from-your-browser-with-WebRTC<p>Can I ring my web browser whenever someone calls me on my number, and answer directly from my web browser ? Well, at APIdaze, we do know how to ring regular phones and SIP terminals, but we must admit that we don't know how to ring web browsers. Does it matter ? Not really, because web technologies like Ajax and WebSockets are here to help pushing events to your browser. And great APIs like Google Channel API and PubNub do it very well ! </p>
<blockquote>
<p>In the VoIP world, ringing a phone is a <em>signaling</em> function, handled by a <em>protocol</em> like SIP or XMPP. Here, this signaling function is up to the developer.</p>
</blockquote>
<p>Let's take a look by the example, with Google App Engine and using the Google Channel API.</p>
<h2>What we need</h2>
<p>Two things mostly :</p>
<ul>
<li>an API to push information to the web browser that a call is coming. This is the job of the Google Channel API, even though PubNub would fit here too.</li>
<li>a technology that allows my web browser to have a direct voice chat with APIdaze's PSTN gateway. That sounds close to the definition of WebRTC !</li>
</ul>
<blockquote>
<p>The useful information passed through the Google Channel API is a Unix <code>uuid</code> that actually identifies a live call on APIdaze. From the WebRTC side, we just grab the corresponding call and answer it.</p>
</blockquote>
<h2>The code</h2>
<p>We made a sample Google App Engine application (in Java) available on <a href="https://github.com/apidaze/webrtc_call_monitor">GitHub</a>.</p>
<p>The <code>src/webrtccallmonitor/WebRTCCallMonitorServlet.java</code> file handles the web routing. Depending on the HTTP parameters sent to the application, various actions are taken.</p>
<p>If the request comes from a web browser, display a blank page that will act as our monitoring console. The JavaScript code behind the blank page opens a new Google Channel so we're ready to receive notifications from, and connects to APIdaze's platform as well. You can check the <code>war/clientchannel.jsp</code> to get the content of this page.</p>
<p>Any other HTTP request is considered coming from APIdaze, and our application acts like an ExternalScript by replying with XML instructions. Let's take a closer look at those call requests from APIdaze.</p>
<p>If the HTTP request contains a <code>uuid_to_intercept</code> parameter, this means the call originated from the web monitoring console by the JavaScript code, so the application replies with an <code><intercept/></code>command. Here is the content of the corresponding <code>war/clientintercept.jsp</code> file :</p>
<div class="highlight"><pre><code class="language-text" data-lang="text"><%@ page contentType="text/xml;charset=UTF-8" language="java" %>
<document>
<work>
<answer/>
<intercept><%= request.getAttribute("uuid_to_intercept") %></intercept>
<hangup/>
</work>
</document>
</code></pre></div>
<p>If the HTTP request does not contain any <code>uuid_to_intercept</code> parameter, we're handling a regular call. We need to notify this to the web browser using our Google Channel and place the call on hold and ready for answer.</p>
<p>Call notification is done from the Servlet code (<code>src/webrtccallmonitor/WebRTCCallMonitorServlet.java</code>) :</p>
<div class="highlight"><pre><code class="language-java" data-lang="java"><span class="o">...</span>
<span class="c1">// Notify via Google Channel API that someone is calling</span>
<span class="n">String</span> <span class="n">caller_id_number</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="na">getParameter</span><span class="o">(</span><span class="s">"caller_id_number"</span><span class="o">);</span>
<span class="n">String</span> <span class="n">json</span> <span class="o">=</span> <span class="s">"{\"uuid\": \""</span> <span class="o">+</span> <span class="n">uuid</span> <span class="o">+</span> <span class="s">"\", \"caller_id_number\": \""</span> <span class="o">+</span> <span class="n">caller_id_number</span> <span class="o">+</span> <span class="s">"\"}"</span><span class="o">;</span>
<span class="k">this</span><span class="o">.</span><span class="na">channelService</span><span class="o">.</span><span class="na">sendMessage</span><span class="o">(</span><span class="k">new</span> <span class="nf">ChannelMessage</span><span class="o">(</span><span class="k">this</span><span class="o">.</span><span class="na">token</span><span class="o">,</span> <span class="n">json</span><span class="o">));</span>
<span class="c1">// Return XML instructions to put the call on hold (kind of)</span>
<span class="n">rd</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="na">getRequestDispatcher</span><span class="o">(</span><span class="s">"fromapidaze.jsp"</span><span class="o">);</span>
<span class="o">...</span></code></pre></div>
<p>Below is the content of the <code>war/fromapidaze.jsp</code> file. We're actually looping over the instructions as no <code><hangup/></code> instruction is set, and therefore the caller is effectively put on hold.</p>
<div class="highlight"><pre><code class="language-text" data-lang="text"><%@ page contentType="text/xml;charset=UTF-8" language="java" %>
<document>
<work>
<answer/>
<speak>Thank your for calling us. We're processing your call</speak>
<wait>3</wait>
</work>
</document>
</code></pre></div>
<p>If you have any question or issue, please share with us on GitHub : <a href="https://github.com/apidaze/webrtc_call_monitor">https://github.com/apidaze/webrtc<em>call</em>monitor</a> or by email support@apidaze.io. Thanks !</p>
An ExternalScript in PHP2014-01-15T00:00:00+00:00http://developers.apidaze.io/2014/01/15/an-ExternalScript-in-php<p>Here is a simple example of an ExternalScript that will place incoming calls into an audio conference.</p>
<h2>Set up your ExternalScript URL</h2>
<p>We''ll assume that your ExternalScript will be accessible from Heroku at http://hidden-ridge-9239.herokuapp.com. Hosting your PHP code at Heroku is easy even if you're not familiar with it : <a href="https://devcenter.heroku.com/articles/getting-started-with-php">https://devcenter.heroku.com/articles/getting-started-with-php</a>.</p>
<p>In order to have your calls handled there, you simply need to instruct APIdaze of that URL either by logging in to your APIdaze <a href="https://developers.apidaze.io">developer account</a> and creating an ExternalScript in the API Reference section, or by sending a REST command.</p>
<p>Note that any web PaaS service (e.g. Google App Engine) or private web server will be convenient to host your ExternalScript. APIdaze just needs to access its URL.</p>
<p>Creating an ExternalScript with <code>cURL</code> :</p>
<div class="highlight"><pre><code class="language-text" data-lang="text">$ curl -v -X POST "https://api2.apidaze.io/d3adb33f/externalscripts" -d 'api_secret=223dc42e78cfb84bf618b68069e11986&name=myexternalscript&url=http://hidden-ridge-9239.herokuapp.com'
</code></pre></div>
<h2>PHP</h2>
<div class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp"><?php</span>
<span class="nb">header</span><span class="p">(</span><span class="s1">'Content-Type: text/xml; charset=utf-8'</span><span class="p">);</span>
<span class="k">echo</span> <span class="s2">"</span>
<span class="s2"><document></span>
<span class="s2"> <work></span>
<span class="s2"> <answer/></span>
<span class="s2"> <conference>myconference</conference></span>
<span class="s2"> <hangup/></span>
<span class="s2"> </work></span>
<span class="s2"></document>"</span><span class="p">;</span>
<span class="cp">?></span><span class="x"></span></code></pre></div>
<p>And that's it ! Now every incoming calls will be routed to an audio conference named <code>myconference</code>. If you access this conference from WebRTC, you'll also be able to get more information to your JavaScript codec like who's entering/leaving the conference and who is talking.</p>
Log the HTTP calls made to your ExternalScript2014-01-12T00:00:00+00:00http://developers.apidaze.io/2014/01/12/log-the-HTTP-calls-made-to-your-ExternalScript<p>Every call made to your application, be it from the PSTN, SIP or WebRTC/Flash UDP triggers a call to your ExternalScript, where APIdaze gets the list of instructions to be run. This is why a publicly accessible URL must be attached to your ExternalScript object, using our HTTP/REST API or from the <a href="http://developers.apidaze.io">developer portal</a>.</p>
<p>There are two main reasons why a developer would log the HTTP requests made from APIdaze to his ExternalScript : get useful status codes from, and know from which source the call has been placed. Let us take a look.</p>
<h2>Get status codes from APIdaze</h2>
<p>APIdaze fetches your ExternalScript at least twice : when a call starts, to gather the list of XML instructions to run, and when the last instruction of the list has been run. Some useful variables are returned by APIdaze in the latter, for instance :</p>
<ul>
<li><code>XML_error</code> : any error in your ExternalScript will be reported in this variable</li>
<li><code>exiting</code> : set to true when the last XML instruction has been run</li>
<li><code>hangup_cause</code> and <code>bridge_status</code> : sent as a result of a <dial> command, and can take exmplicit values like <code>NORMAL_CLEARING</code>, <code>USER_BUSY</code>, <code>NO_USER_RESPONSE</code> to let you decide how to handle the call afterwards</li>
</ul>
<h2>Defining the context of call</h2>
<p>When a call is placed, how to know that a call comes from the PSTN, from a SIP account or from a web page using our WebRTC JavaScript API ? The answer is simple : use HTTP.</p>
<p>Every HTTP request APIdaze makes to your ExternalScript contains parameters that let your script know the context of a call.</p>
<p>Variables set when calling from the PSTN :</p>
<div class="highlight"><pre><code class="language-text" data-lang="text">caller_id_number
destination_number
</code></pre></div>
<p>Variables set when calling from a SIP account :</p>
<div class="highlight"><pre><code class="language-text" data-lang="text">sip_from_uri
caller_id_number
destination_number
</code></pre></div>
<p>Calling from WebRTC is a little different. Let us assume that you are running a webpage that allows people to directly place a call as shown on our <a href="https://developers.apidaze.io/webrtc">developer portal</a>. Actually, all the variables set in the first argument of the <code>call</code> function are passed to your ExternalScript.</p>
<div class="highlight"><pre><code class="language-js" data-lang="js"><span class="p">...</span>
<span class="kd">var</span> <span class="nx">channel</span> <span class="o">=</span> <span class="nx">client</span><span class="p">.</span><span class="nx">call</span><span class="p">(</span>
<span class="p">{</span>
<span class="nx">my_parameter_that_contains_a_number</span><span class="o">:</span> <span class="s2">"0033123456789"</span><span class="p">,</span>
<span class="nx">my_web_session_id</span><span class="o">:</span> <span class="s2">"AF8E74E5-3C8B-4D80-A797-3FF85F910B1D"</span>
<span class="p">},</span>
<span class="p">{</span>
<span class="nx">onAnswered</span><span class="o">:</span> <span class="kd">function</span><span class="p">(){</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">"Remote party answered"</span><span class="p">);</span> <span class="p">},</span>
<span class="nx">onRinging</span><span class="o">:</span> <span class="kd">function</span><span class="p">(){</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">"Remote party is ringing"</span><span class="p">);</span> <span class="p">},</span>
<span class="nx">onHangup</span><span class="o">:</span> <span class="kd">function</span><span class="p">(){</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">"Remote party hung up"</span><span class="p">);</span> <span class="p">}</span>
<span class="p">}</span>
<span class="p">);</span></code></pre></div>
<p>In the above example, the variables <code>my_parameter_that_contains_a_number</code> and <code>my_web_session_id</code> are passed to your ExternalScript, therefore allowing you to grant or refuse the call based on who is calling.</p>
<h2>PHP</h2>
<p>The code snippet below shows how to log the HTTP parameters of the requests made by APIdaze to a local file <code>/tmp/log-urltest.txt</code>. The XML instructions to run on APIdaze indicate that any incoming call from number <code>33987654321</code> are routed to <code>33987654321</code>, whereas calls from any other source are refused.</p>
<div class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp"><?php</span>
<span class="nv">$date</span> <span class="o">=</span> <span class="nb">date</span><span class="p">(</span><span class="s1">'d-m-Y G:i:s'</span><span class="p">);</span>
<span class="nv">$logs</span> <span class="o">=</span> <span class="s2">"["</span><span class="o">.</span> <span class="nv">$date</span> <span class="o">.</span> <span class="s2">"] START OF PARAMETERS</span><span class="se">\n</span><span class="s2">"</span><span class="p">;</span>
<span class="k">foreach</span><span class="p">(</span><span class="nv">$_GET</span> <span class="k">as</span> <span class="nv">$key</span> <span class="o">=></span> <span class="nv">$value</span><span class="p">)</span> <span class="p">{</span>
<span class="nv">$logs</span> <span class="o">.=</span> <span class="s2">"["</span><span class="o">.</span> <span class="nv">$date</span> <span class="o">.</span> <span class="s2">"] "</span> <span class="o">.</span> <span class="nv">$key</span> <span class="o">.</span> <span class="s2">" : "</span> <span class="o">.</span> <span class="nv">$value</span> <span class="o">.</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">;</span>
<span class="p">}</span>
<span class="nv">$logs</span> <span class="o">.=</span> <span class="s2">"["</span><span class="o">.</span> <span class="nv">$date</span> <span class="o">.</span> <span class="s2">"] END OF PARAMETERS</span><span class="se">\n</span><span class="s2">"</span><span class="p">;</span>
<span class="nv">$fplogs</span> <span class="o">=</span> <span class="nb">fopen</span><span class="p">(</span><span class="s1">'/tmp/log-urltest.txt'</span><span class="p">,</span> <span class="s1">'a+'</span><span class="p">);</span>
<span class="nb">fwrite</span><span class="p">(</span><span class="nv">$fplogs</span><span class="p">,</span> <span class="nv">$logs</span><span class="p">);</span>
<span class="nb">fclose</span><span class="p">(</span><span class="nv">$fplogs</span><span class="p">);</span>
<span class="o">...</span>
<span class="nb">header</span><span class="p">(</span><span class="s1">'Content-Type: text/xml; charset=utf-8'</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nv">$_GET</span><span class="p">[</span><span class="s1">'caller_id_number'</span><span class="p">]</span> <span class="o">!=</span> <span class="s1">'33987654321'</span><span class="p">)</span> <span class="p">{</span>
<span class="k">echo</span> <span class="s2">"</span>
<span class="s2"><document></span>
<span class="s2"> <work></span>
<span class="s2"> <speak>Sorry, we cannot process your call, bye.</speak></span>
<span class="s2"> <hangup/></span>
<span class="s2"> </work></span>
<span class="s2"></document>"</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="k">echo</span> <span class="s2">"</span>
<span class="s2"><document></span>
<span class="s2"> <work></span>
<span class="s2"> <dial> </span>
<span class="s2"> <number>0033123456789</number></span>
<span class="s2"> </dial></span>
<span class="s2"> <hangup/></span>
<span class="s2"> </work></span>
<span class="s2"></document>"</span><span class="p">;</span>
<span class="p">}</span>
<span class="cp">?></span><span class="x"></span></code></pre></div>
<p>Sample content of the <code>/tmp/urltest.txt</code> log file :</p>
<div class="highlight"><pre><code class="language-text" data-lang="text">[2014-01-12 10:48:38] START OF PARAMETERS
[2014-01-12 10:48:38] session_id : b57cd556-dc0d-11e3-89d5-07add783a6d5
[2014-01-12 10:48:38] uuid : b57cd556-dc0d-11e3-89d5-07add783a6d5
[2014-01-12 10:48:38] destination_number : 0033123456789
[2014-01-12 10:48:38] caller_id_number : 33987654321
[2014-01-12 10:48:38] caller_username : anonymous
[2014-01-12 10:48:38] url : http://mysite.mydomain.com/myexternalscript/answer.php
[2014-01-12 10:48:38] END OF PARAMETERS
[2014-01-12 10:49:07] START OF PARAMETERS
[2014-01-12 10:49:07] session_id : b57cd556-dc0d-11e3-89d5-07add783a6d5
[2014-01-12 10:49:07] hangup_cause : NORMAL_CLEARING
[2014-01-12 10:49:07] bridge_status : SUCCESS
[2014-01-12 10:49:07] uuid : b57cd556-dc0d-11e3-89d5-07add783a6d5
[2014-01-12 10:49:07] destination_number : 0033123456789
[2014-01-12 10:49:07] caller_id_number : 33987654321
[2014-01-12 10:49:07] caller_username : anonymous
[2014-01-12 10:49:07] url : http://mysite.mydomain.com/myexternalscript/answer.php
[2014-01-12 10:49:07] work_tag : <hangup/>
[2014-01-12 10:49:07] exiting : true
[2014-01-12 10:49:07] END OF PARAMETERS
</code></pre></div>