Transfer a call using API

This API enables an in-progress or active call to a different URL and fetch and execute XML from a new URL. If the call (the A leg) is in a Dial, you can also transfer the other party (the B leg) at the same time or only transfer the B leg to an URL. This is useful for many applications where you want to asynchronously change the behavior of a live call. For example, you can play music while the call is on hold, queue calls, transfer calls etc. Check out more about Transfer API here

POST https://api.plivo.com/v1/Account/{auth_id}/Call/{call_uuid}/

Prerequisites

  1. Sign up for a free Plivo trial account.
  2. Check out our Helper Libraries page and install the right helper based on the programming language you want to use.
  3. Buy a Plivo phone number. A phone number is required to receive calls. You can buy a Plivo phone number in over 20+ countries through the Buy Numbers tab on your Plivo account UI. Check the Voice API coverage page for all the supported countries.
  4. Use a web hosting service to host your web application. There are many inexpensive cloud hosting providers that you can use for just a few dollars a month. Follow the instructions of your hosting provider to host your web application.

Set up a Web Server

Let’s assume your web server is located at example.com. Below is a snippet to set up a route on your webserver. Lets call it, transfer_api. Now when we send an HTTP request to example.com/call_transfer this route will be invoked. This route will return an XML which will read out a message for the caller and when 1 is pressed, transfer_action route is invoked. This will initiate the Transfer API.

Note: For PHP, the route will be example.com/transfer_api.php.

  1. Copy the relevant code below into a text file and save it. Lets call it, transfer_api.
  2. Next, you will now have to configure this URL in your Plivo application.

Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import plivo, plivoxml
from flask import Flask, Response, request, url_for

app = Flask(__name__)

# When the call is answered, a message is played which prompts the user to press 1 to transfer the call.
# Once the digit is pressed, the transfer API request is made and the call is transfered to another number.

@app.route('/call_transfer/', methods=['POST', 'GET'])
def call_transfer():
    response = plivoxml.Response()
    getdigits_action_url = url_for('transfer_action', _external=True)
    getDigits = plivoxml.GetDigits(action=getdigits_action_url,
            method='GET', timeout=7, numDigits=1,
            retries=1, redirect='false')
    getDigits.addSpeak("Press 1 to transfer this call")
    response.add(getDigits)
    params = {
        'length' : "10" # Time to wait in seconds
    }
    response.addWait(**params)
    print response.to_xml()
    return Response(str(response), mimetype='text/xml')

# The Transfer API is invoked by the Get Digits action URL
@app.route('/transfer_action/', methods=['POST', 'GET'])
def transfer_action():
    auth_id = "Your_AUTH_ID"
    auth_token = "Your_AUTH_TOKEN"
    p = plivo.RestAPI(auth_id, auth_token)

    digit = request.args.get('Digits')
    call_uuid = request.args.get('CallUUID')
    print "Call UUID is : %s " % (call_uuid)
    print "Digit pressed is : %s " % (digit)

    if digit == "1":
        params = {
            'call_uuid' : call_uuid, # ID of the call
            'aleg_url' : "https://example.com/connect/", # URL to transfer for aleg
            'aleg_method' : "GET" # ethod to invoke the aleg_url
        }
        response = p.transfer_call(params)
    else :
        print "Wrong Input"
    print str(response)
    return Response(str(response), mimetype='text/plain')

if __name__=='__main__':
    app.run(host='0.0.0.0',debug='True')
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
require 'rubygems'
require 'sinatra'
require 'plivo'
include Plivo

# When the call is answered, a message is played which prompts the user to press 1 to transfer the call.
# Once the digit is pressed, the transfer API request is made and the call is transfered to another number.

get '/call_transfer/' do
    r = Response.new()
    getdigits_action_url = "https://example.com/transfer_action/"
    params = {
        'action' => getdigits_action_url,
        'method' => 'GET',
        'timeout' => '7',
        'numDigits' => '1',
        'retries' => '1',
        'redirect' => 'false'
    }
    getDigits = r.GetDigits(params)
    getDigits.addSpeak("Press 1 to transfer this call")

    params = {
        'length' => "10" # Time to wait in seconds
    }
    r.addWait(params)

    puts r.to_xml()
    content_type 'text/xml'
    return r.to_s()
end

# The Transfer API is invoked by the Get Digits action URL
get '/transfer_action/' do
    AUTH_ID = "Your_AUTH_ID"
    AUTH_TOKEN = "Your_AUTH_TOKEN"
    p = RestAPI.new(AUTH_ID, AUTH_TOKEN)

    digit = params[:Digits]
    call_uuid = params[:CallUUID]
    print "Digit pressed: #{digit}"
    print "Call UUID: #{call_uuid}"

    if (digit == "1")
        params = {
            'call_uuid' => call_uuid, # ID of the call
            'aleg_url' => "https://example.com/connect/", # URL to transfer for aleg
            'aleg_method' => "GET" # ethod to invoke the aleg_url
        }
        response = p.transfer_call(params)
        print response
    else
        print "Wrong Input"
    end
end
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
var express = require('express');
var app = express();
var plivo = require('plivo');

app.set('port', (process.env.PORT || 5000));

// When the call is answered, a message is played which prompts the user to press 1 to transfer the call.
// Once the digit is pressed, the transfer API request is made and the call is transfered to another number.

app.get('/call_transfer/', function(request, response){
    var r = plivo.Response();

    var getdigits_action_url = "https://example.com/transfer_action/";
    var params = {
        'action': getdigits_action_url,
        'method': 'GET',
        'timeout': '7',
        'numDigits': '1',
        'retries': '1',
        'redirect': 'false'
    };
    var getDigits = r.GetDigits(params);
    getDigits.addSpeak("Press 1 to transfer this call");

    params = {
        'length': "10" // Time to wait in seconds
    };
    r.addWait(params);

    console.log(r.toXML());
    response.set({'Content-Type': 'text/xml'});
    response.send(r.toXML());
});

// The Transfer API is invoked by the Get Digits action URL
app.get('/speak_action/', function(request, response){
    var AUTH_ID = "Your_AUTH_ID";
    var AUTH_TOKEN = "Your_AUTH_TOKEN";
    var p = plivo.RestAPI.new(AUTH_ID, AUTH_TOKEN);

    var digit = request.query.Digits || request.body.Digits;
    var call_uuid = request.query.CallUUID || request.body.CallUUID;
    console.log("Digit pressed: ", digit);
    console.log("Call UUID: ", call_uuid);

    if (digit === "1") {
        var params = {
            'call_uuid': call_uuid, // ID of the call
            'aleg_url': "https://example.com/connect/", // URL to transfer for aleg
            'aleg_method': "GET" // method to invoke the aleg_url
        };
        response = p.transfer_call(params);
    } else {
        console.log("Wrong Input");
        response = "Error";
    }
    return response;
});

app.listen(app.get('port'), function() {
    console.log('Node app is running on port', app.get('port'));
});
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<?php    
    require 'vendor/autoload.php';
    use Plivo\Response;
    # When the call is answered, a message is played which prompts the user to press 1 to transfer the call.
    # Once the digit is pressed, the transfer API request is made and the call is transfered to another number.
    
    $r = new Response();

    $getdigits_action_url = "https://example.com/transfer_action.php";
    $params = array(
        'action' => $getdigits_action_url, # The URL to which the digits are sent.
        'method' => 'GET', # Submit to action URL using GET or POST.
        'timeout' => '7', # Time in seconds to wait to receive the first digit.
        'numDigits' =>  '1', # Maximum number of digits to be processed in the current operation.
        'retries' => '1', # Indicates the number of retries the user is allowed to input the digits
        'redirect' => 'false' # Redirect to action URL if true. If false,only request the URL and continue to next element.
    );
    $getDigits = $r->addGetDigits($params);
    $getDigits->addSpeak("Press 1 to transfer your call");
    $waitparam = array(
        'length' => '10'
    );
    $r->addWait($waitparam);

    Header('Content-type: text/xml');
    echo($r->toXML());
?>

<!-- transfer_action.php -->

<?php
    require 'vendor/autoload.php';
    use Plivo\RestAPI;

    $auth_id = "Your_AUTH_ID";
    $auth_token = "Your_AUTH_TOKEN";
    $p = new RestAPI($auth_id, $auth_token);

    $digit = $_REQUEST['Digits'];
    $call_uuid = $_REQUEST['CallUUID'];
    error_log($digit);
    error_log($call_uuid);

    if ($digit == "1"){
        $params = array(
            'call_uuid' => $call_uuid, # ID of the call
            'aleg_url' => 'https://example.com/connect.php', # URL to transfer for aleg
            'aleg_method' => 'GET', # Method to invoke the aleg_url
        );
        $resp = $p->transfer_call($params);
        print_r ($resp);
    } else {
        print ("Wrong Input");
    }
?>
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
// transferApi.java
package plivoexample;

import java.io.IOException;
import com.plivo.helper.exception.PlivoException;
import com.plivo.helper.xml.elements.GetDigits;
import com.plivo.helper.xml.elements.PlivoResponse;
import com.plivo.helper.xml.elements.Speak;
import com.plivo.helper.xml.elements.Wait;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class transferApi extends HttpServlet {
    private static final long serialVersionUID = 1L;
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {

        PlivoResponse response = new PlivoResponse();
        GetDigits gd = new GetDigits();
        gd.setAction("https://example.com/transfer_action");
        gd.setMethod("GET");
        gd.setTimeout(7);
        gd.setNumDigits(1);
        gd.setRetries(1);
        gd.setRedirect(false);

        Speak spk = new Speak("Press 1 to transfer your call");
        Wait wait = new Wait();
        wait.setLength(10);

        try {
            gd.append(spk);
            response.append(gd);
            response.append(wait);
            System.out.println(response.toXML());
            resp.addHeader("Content-Type", "text/xml");
            resp.getWriter().print(response.toXML());;
        } catch (PlivoException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws Exception {
        String port = System.getenv("PORT");
        if(port==null)
            port ="8000";
        Server server = new Server(Integer.valueOf(port));
        ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
        context.setContextPath("/");
        server.setHandler(context);
        context.addServlet(new ServletHolder(new transferApi()),"/call_transfer/");
        context.addServlet(new ServletHolder(new transferAction()),"/transfer_action");
        server.start();
        server.join();
    }
}

// transferAction.java
package plivoexample;

import java.io.IOException;
import java.util.LinkedHashMap;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.plivo.helper.api.client.RestAPI;
import com.plivo.helper.api.response.response.GenericResponse;
import com.plivo.helper.exception.PlivoException;

public class transferAction extends HttpServlet {
    private static final long serialVersionUID = 1L;
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        String auth_id = "Your_AUTH_ID";
        String auth_token = "Your_AUTH_TOKEN";
        RestAPI api = new RestAPI(auth_Id, auth_Token, "v1");

        String digit = req.getParameter("Digits");
        String call_uuid = req.getParameter("CallUUID");
        System.out.println("Digit: " + digit + " Call UUID: " + call_uuid);

        if(digit.equals("1")) {
            LinkedHashMap<String, String> parameters = new LinkedHashMap<String, String>();
            parameters.put("call_uuid",call_uuid);
            parameters.put("aleg_url","https://example.com/connect/");
            parameters.put("aleg_method","GET");

            try {
                GenericResponse transfer = api.transferCall(parameters);
                System.out.println(transfer);
            } catch (PlivoException e) {
                System.out.println(e.getLocalizedMessage());
            }
        } else {
            System.out.println("Wrong Input");
        }
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
using System;
using System.Collections.Generic;
using System.Diagnostics;
using RestSharp;
using Plivo.XML;
using Plivo.API;
using Nancy;

namespace transfer_api
{
    public class Program : NancyModule
    {
        public Program()
        {
            // When the call is answered, a text is played which prompts the user to press 1 to transfer the call.
            // Once the digit is pressed, the transfer API request is made and the call is transfered to another number.

            Get["/call_transfer/"] = x =>
            {
                Plivo.XML.Response resp = new Plivo.XML.Response();
                String getdigits_action_url = "http://example.com/transfer_action/";

                // Add GetDigits XML Tag
                GetDigits gd = new GetDigits("", new Dictionary<string, string>()
                {
                    {"action",getdigits_action_url}, // The URL to which the digits are sent.
                    {"method","GET"}, // Submit to action URL using GET or POST.
                    {"timeout","7"}, // Time in seconds to wait to receive the first digit.
                    {"retries","1"}, // Indicates the number of retries the user is allowed to input the digits
                    {"redirect","false"}, // Redirect to action URL if true. If false,only request the URL and continue to next element.
                    {"numDigits","1"}
                });

                // Add Speak XML Tag
                gd.AddSpeak("Press 1 to transfer this call", new Dictionary<string, string>());
                resp.Add(gd);

                // Add Wait XML Tag
                resp.AddWait(new Dictionary<string, string>()
                {
                    {"length","10"}
                });

                Debug.WriteLine(resp.ToString());

                var output = resp.ToString();
                var res = (Nancy.Response)output;
                res.ContentType = "text/xml";
                return res;
            };

            // The Transfer API is invoked by the Get Digits action URL

            Get["/transfer_action/"] = x =>
            {
                String digits = Request.Query["Digits"];
                String uuid = Request.Query["CallUUID"];
                Debug.WriteLine("Digit pressed: {0}, Call UUID: {1}", digits, uuid);

                if (digits == "1")
                {
                    RestAPI plivo = new RestAPI("Your_AUTH_ID", "Your_AUTH_TOKEN");

                    // Transfer API
                    IRestResponse<GenericResponse> resp = plivo.transfer_call(new Dictionary<string, string>()
                    {
                        { "call_uuid", uuid }, // ID of the call
                        { "aleg_url", "http://example.com/connect/" }, // URL to transfer for aleg
                        { "aleg_method", "GET" } // Method to invoke the aleg_url
                    });

                    Debug.WriteLine(resp.Content);
                }
                else
                {
                    Debug.WriteLine("Invalid");
                }
                return "Transfer API";
            };
        }
    }
}

Create an Application

  1. Create an Application by visiting the Application Page and click on New Application or by using Plivo’s Application API.
  2. Give your application a name. Lets call it Transfer API. Enter your server URL (e.g., http://www.example.com/transfer_api) in the Answer URL field and set the method as POST. See our Application API docs to learn how to modify your application through our APIs.
  3. Click on Create to save your application.

Create Transfer API Application

Assign a Plivo number to your app

  1. Navigate to the Numbers page and select the phone number you want to use for this app.
  2. Select Transfer Api (name of the app) from the Plivo App dropdown list.
  3. Click on ‘Update’ to save.

Create Transfer API Application

If you don’t have a number, go to the Buy Number page to purchase a Plivo phone number.

Phone Number Search

Test it out

When you make a call to your Plivo number, the call will be answered by Plivo and the message “Press 1 to transfer this call” will be played. If you press 1, the Transfer API is used to transfer the call to another number.

Sample XML

Here is the XML returned from /call_transfer/:

<Response>
    <GetDigits redirect="false" retries="1" method="GET" numDigits="1" action="http://example.com/transfer_action/" timeout="7">
        <Speak>Press 1 to transfer your call</Speak>
    </GetDigits>
    <Wait length="10"/>
</Response>

Here is the response from /transfer_action/:

Digit: 1 
Call UUID: 2d3ccd56-c954-11e4-aaa3-fb391e29dbd3


(202, {
        u'call_uuids': [
            u'e66aa1a0-9587-11e4-9d37-c15e0b562efe'
        ], 
        u'message': u'transfer executed', 
        u'api_id': u'eb8c80ae-9587-11e4-b423-22000ac8a2f8'
    }
)

<Response>
    <Speak>Connecting your call</Speak>
    <Dial>
        <Number>1111111111</Number>
    </Dial>
</Response>

Next Step

Learn how to Forward Calls to a SIP Endpoint.

  1. Make an Outbound Call
  2. Play a Text-to-speech Message
  3. Connect Call to a Second Person
  4. Greet Caller by Name
  5. Play MP3/WAV Audio to Caller
  6. Hangup Using API
  7. Receive Incoming Call
  8. Forward Incoming Call
  9. Record Using API
  10. Screen Incoming Call
  11. Reject incoming call
  12. Get Details of all Calls
  13. Get Details of a single Call
  14. Get Details of Live Calls
  15. Build an IVR Phone Menu
  16. Conference Call
  17. Call Forward
  18. SIP Endpoint (Direct-Dial)
  19. Inbound Trunk
  20. Outbound Trunk