Handle an incoming call with Java

Now that you know how to call yourself using the Voice API, learn how to handle incoming calls.

In this guide you will learn:

What you need to know before you start

Before you can get started, you need the following already set up:

  • Set all Voice API configuration settings.
  • JDK 8 or later and a familiarity with how to create a new Java application.
  • Gradle and a familiarity with how use the Gradle build tools.
  • ngrok. You'll use ngrok to open a tunnel to your local server.

Set up your Java application

Create a new folder where you want to keep your app project. Then, open a terminal or command prompt to that location.

Create a new Java application using Gradle with the following command:

Copy
Copied
gradle init

In the prompts, select that you want to create an application, name your project and source package app, and then accept the defaults for the rest of the options.

Install your dependencies

We will be using Springboot to create a lightweight webserver that will listen for HTTP requests from the Sinch servers to handle incoming calls. We'll be using Lombok to deserialize requests.

In your project folder, navigate to the /app folder and open the build.gradle file. Replace all of the code in the file with the following code:

Copy
Copied
    plugins {
      id 'application'
      id 'org.springframework.boot' version '2.5.5'
      id 'io.spring.dependency-management' version '1.0.11.RELEASE'
      id 'java'
    }

    configurations {
      compileOnly {
        extendsFrom annotationProcessor
      }
    }

    repositories {
      mavenCentral()
    }

    dependencies {
      implementation 'org.springframework.boot:spring-boot-starter-web'
      testImplementation 'org.springframework.boot:spring-boot-starter-test'
    }
    
    application {
      mainClass = 'app.App'
    }

Save and close the file.

Modify your application

Open the App.java file in your project folder, located in \app\scr\main\java\app, and populate that file with the "App.java" code found on this page and save the file.

App.java

This file is used to start a lightweight webserver to handle incoming calls.

package app;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@SpringBootApplication
public class App {

	public static void main(String[] args) {
		SpringApplication.run(App.class, args);
	}

	@Controller
	static class WebhookController {

		@PostMapping
		@ResponseBody
		String webhook() {
			
		    var response = String.join("\n"
				, "{"
				, " \"instructions\": ["
				, "    {"
				, "     \"name\": \"say\","
				, "     \"text\": \"Hi, thank you for calling your Sinch number. Congratulations! You just responded to a phone call.\","
				, "     \"locale\": \"en-US\""
				, "    }"
				, "   ],"
				, "  \"action\": {"
				, "     \"name\": \"hangup\""
				, "    }"
				, "}");
			
		    return response;	
		}
	}
}

This code starts your webserver and contains the logic to respond to incoming callbacks from the Sinch servers.

Start your server

At this point, you can start your server with the following command:

Copy
Copied
gradle run

Start your ngrok tunnel

Now you need to start your ngrok tunnel so that the Sinch servers can access the webserver running on your local machine. Run the following command to start your tunnel:

Copy
Copied
ngrok http 8080

This starts a tunnel to your webserver, which is running on port 8080 of your localhost.

Copy the http ngrok URL. Navigate to your app on your dashboard. Under the Settings section, you'll see a field labeled "Callback URL." Paste your ngrok URL into that field and click Save.

Now your server is listening and your callback URL is configured, so you're almost ready to test everything and make a phone call. But before we do, let's take a closer look at callbacks. If you already know about callbacks, skip right to calling your Sinch phone number.

Understanding callbacks

Callbacks (also known as "webhooks") are the method that the Voice API uses to figure out what you want to do with a call. Basically, a callback is a request that the Sinch servers send to your server whenever something happens (otherwise known as an "event") in the call that requires some input from you. There are a few different types of events, but the two we are concerned about for this guide are the Incoming Call Event and the Disconnected Call Event.

An Incoming Call Event (or "ICE") happens whenever someone calls one of your Sinch numbers. In essence, someone dials your number and so Sinch servers reach out to you and say "how do you want me to handle this call?"

Most callback events expect a response, depending on the event. The Incoming Call Event expects to receive back a SVAML object in response. You can read more about SVAML here, but just know that SVAML is a markup language Sinch developed to control calls.

The diagram below demonstrates exactly what's happening:

incoming call diagram

  1. Someone dials your Sinch number from a handset.
  2. The Sinch servers create an ICE and send a POST request to your server.
  3. Your server listens for the request and sends back a SVAML response to tell the Sinch server how to handle the call.

In this sample application, this is the SVAML object that you will use to respond to the callback:

Copy
Copied
{
  "instructions": [
    {
      "name": "say",
      "text": "Hi, thank you for calling your Sinch number. Congratulations! You just responded to a phone call.",
      "local": "en-US"
    }
  ],
  "action": {
    "name": "hangup"
  }
}

A SVAML object has two parts: instructions and an action.

  • Instructions: Things you want to be done on the call without changing the state of the call. You can have as many instructions as you need. In this case, we want to play a voice that reads out a text message.
  • Action: Things you want to be done to the call to change its state in some way. Each SVAML object can only have one action. In this case, we want to hang up and end the call.

And that's it! Now we can test.

Call your Sinch phone number

Look up the free Sinch number assigned to your app and call it using your phone. The call should be picked up by the Sinch servers and you should hear the text from the instruction. Now you know how to handle an incoming call.

Next steps

Learn more about the Voice API:

Was this page helpful?

App.java

This file is used to start a lightweight webserver to handle incoming calls.

package app;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@SpringBootApplication
public class App {

	public static void main(String[] args) {
		SpringApplication.run(App.class, args);
	}

	@Controller
	static class WebhookController {

		@PostMapping
		@ResponseBody
		String webhook() {
			
		    var response = String.join("\n"
				, "{"
				, " \"instructions\": ["
				, "    {"
				, "     \"name\": \"say\","
				, "     \"text\": \"Hi, thank you for calling your Sinch number. Congratulations! You just responded to a phone call.\","
				, "     \"locale\": \"en-US\""
				, "    }"
				, "   ],"
				, "  \"action\": {"
				, "     \"name\": \"hangup\""
				, "    }"
				, "}");
			
		    return response;	
		}
	}
}