Record Phone Calls in Java

In this guide we'll show you how to use Programmable Voice to record phone calls with your Java web application.

You will learn how to record inbound and outbound calls. In both examples we'll use Twilio's Java SDK.

Setup your web application

Incoming Voice

Twilio makes answering a phone call as easy as responding to an HTTP request. When a phone number you have bought through Twilio receives an incoming call, Twilio will send an HTTP request to your web applicatoin asking for instructions on how to handle the call. Your server will respond with an XML document containing TwiML that instructs Twilio on what to do with the call. Those instructions can direct Twilio to read out a message, play an MP3 file, make a recording and much more.

To start answering phone calls, you must:

  • Buy and configure a Twilio-powered phone number capable of making and receiving phone calls, and point it at your web application
  • Write a web application to tell Twilio how to handle the incoming call using TwiML
  • Make your web application accessible on the Internet so Twilio can make an HTTP request when you receive a call

Buy and configure a phone number

In the Twilio Console, you can search for and buy phone numbers in countries around the world. Numbers that have the Voice capability can make and receive voice phone calls from just about anywhere on the planet.

Search for voice capable numbers

Once you purchase a number, you'll need to configure that number to send a request to your web application. This callback mechanism is called a webhook. This can be done in the number's configuration page.

configure an incoming phone number URL

What is a Webhook?

Webhooks are user-defined HTTP callbacks. They are usually triggered by some event, such as receiving an SMS message or an incoming phone call. When that event occurs, Twilio makes an HTTP request (usually a POST or a GET) to the URL configured for the webhook.

To handle a webhook, you only need to build a small web application that can accept the HTTP requests. Almost all server-side programming languages offer some framework for you to do this. Examples across languages include ASP.NET MVC for C#, Servlets and Spark for Java, Express for Node.js, Django and Flask for Python, and Rails and Sinatra for Ruby. PHP has its own web app framework built in, although frameworks like Laravel, Symfony and Yii are also popular.

Whichever framework and language you choose, webhooks function the same for every Twilio application. They will make an HTTP request to a URI that you provide to Twilio. Your application performs whatever logic you feel necessary - read/write from a database, integrate with another API or perform some computation - then replies to Twilio with a TwiML response with the instructions you want Twilio to perform.

What is TwiML?

TwiML is the Twilio Markup Language, which is just to say that it's an XML document with special tags defined by Twilio to help you build your SMS and voice applications. TwiML is easier shown than explained:

<?xml version="1.0" encoding="UTF-8"?>
<Response>
    <Say>Thanks for calling!</Say>
</Response>

Every TwiML document will have the root <Response> element and within that can contain one or more verbs. Verbs are actions you'd like Twilio to take, such as <Say> a greeting to a caller, or send an SMS <Message> in reply to an incoming message. For a full reference on everything you can do with TwiML, refer to our TwiML API Reference.

Record an inbound phone call

Now comes the fun part - writing Java that will handle an incoming HTTP request from Twilio!

In this example we'll use Java Servlets to respond to the Twilio webhook. We'll then use TwiML to tell Twilio how to handle the call.

Loading Code Samples...
Language
SDK Version:
  • 6.x
  • 7.x
import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.twilio.sdk.verbs.*;

@SuppressWarnings("serial")
@WebServlet("/voice")
public class RecordServlet extends HttpServlet {

  // Handle HTTP POST to /record
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    // Create a TwiML builder object
    TwiMLResponse twiml = new TwiMLResponse();

    try {
      // Use <Say> to give the caller some instructions
      twiml.append(new Say("Hello. Please leave a message after the beep."));

      // Use <Record> to record the caller's message
      twiml.append(new Record());

      // End the call with <Hangup>
      twiml.append(new Hangup());
    } catch (TwiMLException e) {
      e.printStackTrace();
    }

    // Render TwiML as XML
    response.setContentType("text/xml");
    response.getWriter().print(twiml.toXML());
  }
}
import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.twilio.twiml.*;

@SuppressWarnings("serial")
@WebServlet("/voice")
public class RecordServlet extends HttpServlet {

  // Handle HTTP POST to /record
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    // Use <Say> to give the caller some instructions
    Say instructions = new Say.Builder("Hello. Please leave a message after the beep.").build();

    // Use <Record> to record the caller's message
    Record record = new Record.Builder().build();

    // End the call with <Hangup>
    Hangup hangup = new Hangup();

    // Create a TwiML builder object
    VoiceResponse twiml = new VoiceResponse.Builder()
        .say(instructions)
        .record(record)
        .hangup(hangup)
        .build();

    // Render TwiML as XML
    response.setContentType("text/xml");

    try {
      response.getWriter().print(twiml.toXml());
    } catch (TwiMLException e) {
      e.printStackTrace();
    }



  }
}
Use the <Record> TwiML verb to record a message from the caller
Record part of an incoming call

Use the <Record> TwiML verb to record a message from the caller

Record an outgoing phone call

When you make outgoing calls with the Twilio REST API, you can tell Twilio to record the entire call from beginning to end. But first, we'll need to get your credentials to make that request.

Retrieve your Twilio account credentials

First, you'll need to get your Twilio account credentials. They consist of your AccountSid and your Auth Token. They can be found on the home page of the console.

Retrieve Your Twilio Credentials

Make and record an outbound call

Just pass an extra "record" argument to "client.account.calls.create()" and Twilio will record the entire phone call.

Loading Code Samples...
Language
SDK Version:
  • 6.x
  • 7.x
Format:
  • JSON
  • XML
// Install the Java helper library from twilio.com/docs/java/install
import com.twilio.sdk.TwilioRestClient;
import com.twilio.sdk.TwilioRestException;
import com.twilio.sdk.resource.factory.CallFactory;
import com.twilio.sdk.resource.instance.Call;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;

import java.util.ArrayList;
import java.util.List;

public class Example {

    // Find your Account Sid and Token at twilio.com/user/account
    public static final String ACCOUNT_SID = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
    public static final String AUTH_TOKEN = "your_auth_token";

    public static void main(String[] args) throws TwilioRestException {
        TwilioRestClient client = new TwilioRestClient(ACCOUNT_SID, AUTH_TOKEN);

        // Build a filter for the CallList
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        params.add(new BasicNameValuePair("Url", "http://demo.twilio.com/docs/voice.xml"));
        params.add(new BasicNameValuePair("To", "+14155551212"));
        params.add(new BasicNameValuePair("From", "+15017250604"));
        params.add(new BasicNameValuePair("Record", "true"));

        CallFactory callFactory = client.getAccount().getCallFactory();
        Call call = callFactory.create(params);
        System.out.println(call.getSid());
    }
}
// Install the Java helper library from twilio.com/docs/java/install
import com.twilio.Twilio;
import com.twilio.rest.api.v2010.account.Call;
import com.twilio.type.PhoneNumber;

import java.net.URI;
import java.net.URISyntaxException;

public class Example {

    // Find your Account Sid and Token at twilio.com/user/account
    public static final String ACCOUNT_SID = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
    public static final String AUTH_TOKEN = "your_auth_token";

    public static void main(String[] args) throws URISyntaxException {
        Twilio.init(ACCOUNT_SID, AUTH_TOKEN);

        Call call = Call.creator(
                new PhoneNumber("+14155551212"),
                new PhoneNumber("+15017250604"),
                new URI("http://demo.twilio.com/docs/voice.xml")
                )
                .setRecord(true)
                .create();

        System.out.println(call.getSid());
    }
}
{
	"sid": "CAa346467ca321c71dbd5e12f627deb854",
	"date_created": "Thu, 19 Aug 2010 00:12:15 +0000",
	"date_updated": "Thu, 19 Aug 2010 00:12:15 +0000",
	"parent_call_sid": null,
	"account_sid": "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
	"to": "+14155551212",
	"formatted_to": "(415) 555-1212",
	"from": "+14158675309",
	"formatted_from": "(415) 867-5309",
	"phone_number_sid": "PNd6b0e1e84f7b117332aed2fd2e5bbcab",
	"status": "queued",
	"start_time": null,
	"end_time": null,
	"duration": null,
	"price": null,
	"direction": "outbound-api",
	"answered_by": null,
	"api_version": "2010-04-01",
	"forwarded_from": null,
	"caller_name": null,
	"uri": "\/2010-04-01\/Accounts\/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\/Calls\/CAa346467ca321c71dbd5e12f627deb854.json",
	"subresource_uris": {
		"notifications": "\/2010-04-01\/Accounts\/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\/Calls\/CAa346467ca321c71dbd5e12f627deb854\/Notifications.json",
		"recordings": "\/2010-04-01\/Accounts\/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\/Calls\/CAa346467ca321c71dbd5e12f627deb854\/Recordings.json"
	}
}
<TwilioResponse>
	<Call>
		<Sid>CAa346467ca321c71dbd5e12f627deb854</Sid>
		<DateCreated>Thu, 19 Aug 2010 00:25:48 +0000</DateCreated>
		<DateUpdated>Thu, 19 Aug 2010 00:25:48 +0000</DateUpdated>
		<ParentCallSid/>
		<AccountSid>ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</AccountSid>
		<To>+14155551212</To>
		<FormattedTo>(415) 555-1212</FormattedTo>
		<From>+14158675309</From>
		<FormattedFrom>(415) 867-5309</FormattedFrom>
		<PhoneNumberSid></PhoneNumberSid>
		<Status>queued</Status>
		<StartTime/>
		<EndTime/>
		<Duration/>
		<Price/>
		<Direction>outbound-api</Direction>
		<AnsweredBy/>
		<ApiVersion>2010-04-01</ApiVersion>
		<ForwardedFrom/>
		<CallerName/>
		<Uri>/2010-04-01/Accounts/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Calls/CAa346467ca321c71dbd5e12f627deb854</Uri>
		<SubresourceUris>
			<Notifications>/2010-04-01/Accounts/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Calls/CAa346467ca321c71dbd5e12f627deb854/Notifications</Notifications>
			<Recordings>/2010-04-01/Accounts/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Calls/CAa346467ca321c71dbd5e12f627deb854/Recordings</Recordings>
		</SubresourceUris>
	</Call>
</TwilioResponse>
Record an outbound call with the Twilio REST API
Record an outbound call

Record an outbound call with the Twilio REST API

Once the call is complete, you can listen to your recordings in your Twilio Console or access them directly through Twilio's REST API.

You can also gain access to the recording as soon as the call is complete by including a "StatusCallbackUrl" with your "client.account.calls.create()" command. At the end of the call, Twilio will send a request to the URL you specified and that request will include a link to the recording's audio file.

You can learn more about the "StatusCallbackUrl" parameter in the Making Calls reference docs.

What's next?

That's how to record phone calls using Twilio and Java. If you'd like to learn more about what you can do with Twilio Voice and Java, check out these additional Guides:

Agustin Camino
Andrew Baker
David Prothero
Rob Spectre
Kevin Whinnery

Need some help?

We all do sometimes; code is hard. Get help now from our support team, or lean on the wisdom of the crowd browsing the Twilio tag on Stack Overflow.

1 / 1
Loading Code Samples...
SDK Version:
  • 6.x
  • 7.x
import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.twilio.sdk.verbs.*;

@SuppressWarnings("serial")
@WebServlet("/voice")
public class RecordServlet extends HttpServlet {

  // Handle HTTP POST to /record
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    // Create a TwiML builder object
    TwiMLResponse twiml = new TwiMLResponse();

    try {
      // Use <Say> to give the caller some instructions
      twiml.append(new Say("Hello. Please leave a message after the beep."));

      // Use <Record> to record the caller's message
      twiml.append(new Record());

      // End the call with <Hangup>
      twiml.append(new Hangup());
    } catch (TwiMLException e) {
      e.printStackTrace();
    }

    // Render TwiML as XML
    response.setContentType("text/xml");
    response.getWriter().print(twiml.toXML());
  }
}
import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.twilio.twiml.*;

@SuppressWarnings("serial")
@WebServlet("/voice")
public class RecordServlet extends HttpServlet {

  // Handle HTTP POST to /record
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    // Use <Say> to give the caller some instructions
    Say instructions = new Say.Builder("Hello. Please leave a message after the beep.").build();

    // Use <Record> to record the caller's message
    Record record = new Record.Builder().build();

    // End the call with <Hangup>
    Hangup hangup = new Hangup();

    // Create a TwiML builder object
    VoiceResponse twiml = new VoiceResponse.Builder()
        .say(instructions)
        .record(record)
        .hangup(hangup)
        .build();

    // Render TwiML as XML
    response.setContentType("text/xml");

    try {
      response.getWriter().print(twiml.toXml());
    } catch (TwiMLException e) {
      e.printStackTrace();
    }



  }
}
SDK Version:
  • 6.x
  • 7.x
Format:
  • JSON
  • XML
// Install the Java helper library from twilio.com/docs/java/install
import com.twilio.sdk.TwilioRestClient;
import com.twilio.sdk.TwilioRestException;
import com.twilio.sdk.resource.factory.CallFactory;
import com.twilio.sdk.resource.instance.Call;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;

import java.util.ArrayList;
import java.util.List;

public class Example {

    // Find your Account Sid and Token at twilio.com/user/account
    public static final String ACCOUNT_SID = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
    public static final String AUTH_TOKEN = "your_auth_token";

    public static void main(String[] args) throws TwilioRestException {
        TwilioRestClient client = new TwilioRestClient(ACCOUNT_SID, AUTH_TOKEN);

        // Build a filter for the CallList
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        params.add(new BasicNameValuePair("Url", "http://demo.twilio.com/docs/voice.xml"));
        params.add(new BasicNameValuePair("To", "+14155551212"));
        params.add(new BasicNameValuePair("From", "+15017250604"));
        params.add(new BasicNameValuePair("Record", "true"));

        CallFactory callFactory = client.getAccount().getCallFactory();
        Call call = callFactory.create(params);
        System.out.println(call.getSid());
    }
}
// Install the Java helper library from twilio.com/docs/java/install
import com.twilio.Twilio;
import com.twilio.rest.api.v2010.account.Call;
import com.twilio.type.PhoneNumber;

import java.net.URI;
import java.net.URISyntaxException;

public class Example {

    // Find your Account Sid and Token at twilio.com/user/account
    public static final String ACCOUNT_SID = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
    public static final String AUTH_TOKEN = "your_auth_token";

    public static void main(String[] args) throws URISyntaxException {
        Twilio.init(ACCOUNT_SID, AUTH_TOKEN);

        Call call = Call.creator(
                new PhoneNumber("+14155551212"),
                new PhoneNumber("+15017250604"),
                new URI("http://demo.twilio.com/docs/voice.xml")
                )
                .setRecord(true)
                .create();

        System.out.println(call.getSid());
    }
}
{
	"sid": "CAa346467ca321c71dbd5e12f627deb854",
	"date_created": "Thu, 19 Aug 2010 00:12:15 +0000",
	"date_updated": "Thu, 19 Aug 2010 00:12:15 +0000",
	"parent_call_sid": null,
	"account_sid": "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
	"to": "+14155551212",
	"formatted_to": "(415) 555-1212",
	"from": "+14158675309",
	"formatted_from": "(415) 867-5309",
	"phone_number_sid": "PNd6b0e1e84f7b117332aed2fd2e5bbcab",
	"status": "queued",
	"start_time": null,
	"end_time": null,
	"duration": null,
	"price": null,
	"direction": "outbound-api",
	"answered_by": null,
	"api_version": "2010-04-01",
	"forwarded_from": null,
	"caller_name": null,
	"uri": "\/2010-04-01\/Accounts\/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\/Calls\/CAa346467ca321c71dbd5e12f627deb854.json",
	"subresource_uris": {
		"notifications": "\/2010-04-01\/Accounts\/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\/Calls\/CAa346467ca321c71dbd5e12f627deb854\/Notifications.json",
		"recordings": "\/2010-04-01\/Accounts\/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\/Calls\/CAa346467ca321c71dbd5e12f627deb854\/Recordings.json"
	}
}
<TwilioResponse>
	<Call>
		<Sid>CAa346467ca321c71dbd5e12f627deb854</Sid>
		<DateCreated>Thu, 19 Aug 2010 00:25:48 +0000</DateCreated>
		<DateUpdated>Thu, 19 Aug 2010 00:25:48 +0000</DateUpdated>
		<ParentCallSid/>
		<AccountSid>ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</AccountSid>
		<To>+14155551212</To>
		<FormattedTo>(415) 555-1212</FormattedTo>
		<From>+14158675309</From>
		<FormattedFrom>(415) 867-5309</FormattedFrom>
		<PhoneNumberSid></PhoneNumberSid>
		<Status>queued</Status>
		<StartTime/>
		<EndTime/>
		<Duration/>
		<Price/>
		<Direction>outbound-api</Direction>
		<AnsweredBy/>
		<ApiVersion>2010-04-01</ApiVersion>
		<ForwardedFrom/>
		<CallerName/>
		<Uri>/2010-04-01/Accounts/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Calls/CAa346467ca321c71dbd5e12f627deb854</Uri>
		<SubresourceUris>
			<Notifications>/2010-04-01/Accounts/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Calls/CAa346467ca321c71dbd5e12f627deb854/Notifications</Notifications>
			<Recordings>/2010-04-01/Accounts/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Calls/CAa346467ca321c71dbd5e12f627deb854/Recordings</Recordings>
		</SubresourceUris>
	</Call>
</TwilioResponse>