Handling Incoming Phone Calls with Java and Twilio
Time to read: 4 minutes
Making outbound phone calls with Java and Twilio is only half of the picture. To build a useful and engaging phone app you will need to handle what happens when people call you back.
To do that, you will need to configure a URL in your Twilio console. Incoming calls will trigger HTTP requests to that URL, and the response to those webhook requests will determine what happens next in the call. The HTTP responses contain an XML dialect called TwiML, which gives you a lot of flexibility in how the call is handled.
In this post I'll show how to set up a web server using Spring Boot to handle incoming calls with a spoken "hello world" and then show how to create a more interesting and interactive setup.
If you want to skip to the end, check out the completed project on GitHub.
Setting up
Before starting out you'll need:
- An installation of Java 8 or newer - I recommend SDKMAN! for installing and managing Java versions.
- A Java IDE - I'm a fan of IntelliJ IDEA, but if you have a favourite that's cool too.
- A Twilio account (if you don't have one yet, sign up for a free account here and receive a $10 credit when you upgrade)
- A Twilio phone number that can make and receive calls
- Either ngrok or the Twilio CLI, so that you canrespond to webhooks in your local development environment
The quickest way to start a brand new Spring Boot project is using the Spring Initializr. This link will take you to a preconfigured setup that has the web dependency selected and some names preconfigured. Load that page, click "Generate", and unzip the downloaded project into an empty directory. Then, open the project in your IDE of choice and let's get going.
Building the application
When you open the code in your IDE you will see the top level of the project. Inside the src/main/java
folder there is a package called com.example.twilio.calls
with a class called TwilioJavaHandlePhoneCallsApplication
in it. You won't need to edit that class but it has a main
method which will be helpful later on.
Creating an HTTP endpoint
Create another class in the same package. Call it PhoneCallHandler
and give it the following content:
[this code with imports on GitHub]
Run this application now, either by running the main
method from TwilioJavaHandlePhoneCallsApplication
in your IDE, or ./mvnw spring-boot:run
in a terminal window at the root of your project.
After it's started up, test it using the command below.
You should see "Hello from your app 👋" as the response.
Returning TwiML over HTTP
So far, so good. The app is handling HTTP requests and returning plain text. Next, modify it to return Twilio Markup Language (TwiML) code with a content-type of application/xml
. TwiML can be written by hand, but it's easier and safer to create it using the Twilio Java Helper library. Add it as a dependency of your project by putting the following in the <dependencies>
section of pom.xml
in the root of your project:
Next, we need to use TwiML to define what happens during the call. This is done in the PhoneCallHandler
class. First, I'll give a short example using text-to-speech to say something. Then, I’ll provide a longer example that shows how you can build an interactive voice app.
<Say> something
Change the content of handleIncomingCall
method in PhoneCallHandler
to return TwiML with a content type of application/xml
:
[this code with imports on GitHub]
This method now returns the following TwiML, which I've formatted in order to make it more readable:
Connecting Twilio to your application
The content returned by handleIncomingCall
is exactly what we need, but Twilio needs to be able to access it from the internet. There are lots of options for hosting Java apps online, but for a quick test like this I like to use a tool called ngrok which can create public URLs that forward to your localhost
web apps.
Once you have installed ngrok, start your app using your IDE or the command from above. Then, run the following command to create a public URL for your local server:
Once it has connected, ngrok displays the randomly generated URL that now points at your application. It should look like https://RANDOM_STRING.ngrok.io
. Open up yourTwilio console to your incoming numbers and choose the number you want to use for this app, orbuy a new one. Edit the number and add your ngrok URL as the webhook for "when a call comes in" (leaving the method as POST
).
Call your number, and listen to the voice saying "Hello from Twilio". Magnificent work. Congratulations 🎉
An interactive example
Let’s step beyond the "hello world" of voice apps. To whet your appetite for some exciting possibilities, I'll show how to build something more fun and interactive. A caller will hear a short menu of options and can choose one by saying a number or typing it on their keypad.
Modify the handleIncomingCall
method to use the <Gather>
TwiML verb, which can do both speech and DTMF tone recognition:
[this code with imports on GitHub]
The caller is prompted to say a number or press a button on their keypad using options which are all documented on the Gather TwiML docs. The most important of these is on line 14 which gives another URL to call when Twilio has recognised a word or a keypad press. If there is no input after the default 5 seconds we say the GOODBYE
message and hang up.
/gatherResult
is a relative URL so another method is needed in PhoneCallHandler
to determine what happens after the caller has made a choice:
[this code including imports on GitHub]
Depending on how the caller made their choice, either digits
or speechResult
will be included in the HTTP request which Twilio sends to find out what to do next. If they chose a valid option we can generate TwiML to tell a joke or play some music by using the <Say>
and <Play>
verbs. The call ends after either of those verbs run. If the caller did something unexpected, the code calls handleIncomingCall
to generate the TwiML that reads the choices to the caller again.
Restart the application and make another call to hear it in action. Fun, isn't it?
Wrapping up
You've learned how to respond to incoming voice calls using Twilio and Java and you've seen that you can chain calls together to build interactive voice apps. Now the limit is your imagination. Whatever you're building, I'd love to hear about it. Please get in touch:
I can't wait to see what you build!
Related Posts
Related Resources
Twilio Docs
From APIs to SDKs to sample apps
API reference documentation, SDKs, helper libraries, quickstarts, and tutorials for your language and platform.
Resource Center
The latest ebooks, industry reports, and webinars
Learn from customer engagement experts to improve your own communication.
Ahoy
Twilio's developer community hub
Best practices, code samples, and inspiration to build communications and digital engagement experiences.