React Native, Java Spring Boot Outbound Call Center with Africa’s Talking


React Native, Java Spring Boot Outbound Call Center with Africa's Talking

Did you know you can easily create a call centre by simply integrating with Africa’s Talking? You can actually have your customer care agents roam around or even work from home and save on rent space at the office. Besides the comfort it affords to your budget and customer care agents, it is a sure way of addressing customer concerns.
Therefore get on to learn how to build an outbound call centre with Africa’s Talking(AT).

Africa’s Talking Call Support Services

Besides making calls to customers and receiving calls from customers, Africa’s Talking(AT) voice integration API gives you a lot of call handling services. You can, for instance, read caller dialled (input) digits during the call, play the caller some music, queue the call, read the caller some text etc.
All the services are geared to help manage customer issues with ease.

Approach and Focus

As seen above, AT calls have endless possibilities and so we must focus.
The focus of this tutorial will be in making calls to the client from our Customer Care Application

How it works

The React App will make a call request to the Africa’s Talking Voice API using the customers’ contact.

AT voice API will notify our Spring Boot API of an intended call, and simply ask “how should I handle the call?”

Our Spring Boot API will then advise the AT Voice API to dial the call.

As stated earlier, you can do more than just dial the call as explained here

The exchanges go on as illustrated below:


We shall first create a Spring Boot API for call handling and then create a React App for making the actual calls.


  1. Knowledge of Java Spring Boot
  2. Knowledge of React Native
  3. Brief Overview of AT’s Voice API Documentation


  • Spring Boot Refresher
  • React Native Refresher
  • An understanding of the AT Outbound calls Voice API

Spring Boot Call Handling API

1. Setup a New Project

Generate a new Spring Boot API here by filling the form as shown below:

For more details refer to this article to learn more on building Spring Boot APIs.

2. Folder Structure

The folder structure should be something like what is shown below:

├── pom.xml
├── src
│   ├── main
│   │   ├── java
│   │   │   └── com
│   │   │   └── anyungu
│   │   │   └── at
│   │   │   └── call
│   │   │   ├──
│   │   │   ├── controllers
│   │   │   │   └──
│   │   │   ├── models
│   │   │   │   ├──
│   │   │   │   └──
│   │   │   └── services
│   │   │   └──
│   │   └── resources
│   │   ├──
│   │   ├── static
│   │   └── templates
│   └── test

└── target

The Controllers folder has a class file which offers endpoints for the AT Voice API to interact with the Spring Boot API.
The Models folder contains data model class files as described in step 4 below.
The Services folder contains the business logic class files.

3. Required Dependencies

In the pom.xml file we shall require the following dependencies:

  • jaxb-runtime
  • spring-boot-starter-web
  • spring-boot-starter-validation

Add the above mentioned in the dependencies section of the pom.xml as show:




4. Africa’s Talking Models

Models are classes to hold/organize/pass around data in Java.

For this project, our Spring Boot will not be writing or reading from the database. Why? This is a demo project.

In a production project, You should probably read from or write to a data storage of your choice.

In the models folder as shown in the folder structure in step 2 above create two model classes called:



The file is used as a model to receive the HTTP POST request that is sent as a call notification from Africa’s Talking Voice API.

P.S 😃 Remember that our App (The call center App) will send a request to AT Voice API and the AT Voice API will send a notification to our Spring Boot API.

Create it with the fields shown in the code below:

public class AtHandleRequest {

    private String isActive;

    private String sessionId;

    private String direction;

    private String callerNumber;

    private String destinationNumber;

    private String dtmfDigits;

    private String recordingUrl;

    private String durationInSeconds;

    private String currencyCode;

    private String amount;

    private String clientDialedNumber;

    public String getIsActive() {
        return isActive;

    public String getClientDialedNumber() {
        return clientDialedNumber;

    public void setClientDialedNumber(String clientDialedNumber) {
        this.clientDialedNumber = clientDialedNumber;

    public void setIsActive(String isActive) {
        this.isActive = isActive;

    public String getSessionId() {
        return sessionId;

    public void setSessionId(String sessionId) {
        this.sessionId = sessionId;

    public String getDirection() {
        return direction;

    public void setDirection(String direction) {
        this.direction = direction;

    public String getCallerNumber() {
        return callerNumber;

    public void setCallerNumber(String callerNumber) {
        this.callerNumber = callerNumber;

    public String getDestinationNumber() {
        return destinationNumber;

    public void setDestinationNumber(String destinationNumber) {
        this.destinationNumber = destinationNumber;

    public String getDtmfDigits() {
        return dtmfDigits;

    public void setDtmfDigits(String dtmfDigits) {
        this.dtmfDigits = dtmfDigits;

    public String getRecordingUrl() {
        return recordingUrl;

    public void setRecordingUrl(String recordingUrl) {
        this.recordingUrl = recordingUrl;

    public String getDurationInSeconds() {
        return durationInSeconds;

    public void setDurationInSeconds(String durationInSeconds) {
        this.durationInSeconds = durationInSeconds;

    public String getCurrencyCode() {
        return currencyCode;

    public void setCurrencyCode(String currencyCode) {
        this.currencyCode = currencyCode;

    public String getAmount() {
        return amount;

    public void setAmount(String amount) {
        this.amount = amount;

Please note that some fields may be missing from the official AT Documentation.

For this project the most important field is the clientDialedNumber.
The clientDialedNumber is the number dialed by our ‘call center’- our React App.


The file is used as a model to return a response to the AT Voice API.

P.S 😃 Note that the AT Voice API accepts XML Responses only. We hope they will be moving to REST or GRAPHQL soon. For now only XML works!

The XmlAccessorType, XmlRootElement, XmlAttribute are all annotations imported from the jaxb-runtime dependency to help map class attributes to XML objects.

Define file as shown below:

@XmlRootElement(name = "Dial")
public class AtXmlResponse {

    protected String phoneNumbers;

    protected String record;

    protected String maxDuration;

    public String getPhoneNumbers() {
        return phoneNumbers;

    public void setPhoneNumbers(String phoneNumbers) {
        this.phoneNumbers = phoneNumbers;

    public String getRecord() {
        return record;

    public void setRecord(String record) {
        this.record = record;

    public String getMaxDuration() {
        return maxDuration;

    public void setMaxDuration(String maxDuration) {
        this.maxDuration = maxDuration;


5. Africa’s Talking Caller Service

The Service layer is where the business logic happens.

For the demo purpose, our logic will stay as simple as getting the notification data from AT Voice API and transmitting it to a dial XML Object that will be returned as a response to the AT Voice API.

In a production project, more can be done e.g queuing for storage, deciding to queue, record the call and etc.

Define the file as shown below:

Please Note:

  • The @Service annotation is imported from ‘org.springframework.stereotype.Service’ and it is used to make the AtCallerService dependency injectable.
  • The if clause confirms for two conditions: if the call is outbound(we can also have inbound calls that should be handled differently) and if the call is active. The second condition !isActive.contentEquals("0") checks if the call has not been terminated (‘0’ indicates the call has been terminated and the data received from AT Voice API should be handled differently)

More about how the XML Response object could be based on the different call handling actions can be found here

6. Africa’s Talking Controller

The Controller offers the AT Voice API a REST endpoint to make Requests to our call handling API as demonstrated in the step How it Works above.

It receives the Post Request Body via the AtHandleRequest model defined in step 4.1 above.

It then passes the received data to the injected AtCallerService dependency that returns a relevant XML Response as shown below:

Define file it as shown below:

Please note:
+The @Autowired annotation is used to inject the AtCallerService dependency. It is imported from: ‘org.springframework.beans.factory.annotation.Autowired’

+The @RestController makes this class a collection of endpoints for each function defined with @PostMapping, @GetMapping, @PutMapping etc. All these annottations are imported from: ‘org.springframework.web.bind.annotation’

+The value variable indicates the API url endpoint

+The produces variable dictates what Media Type a request to this endpoint will provide. It is imported from:‘org.springframework.http.MediaType’

7. Run, Deploy, Start

If you followed the instructions above (especially on how to start the project) the API above should run successfully.

You can read about and run the following commands in the root folder of the project:

mvn clean
mvn install
mvn clean install
mvn test
mvn spring-boot:run

if you used gradle:

gradle build
gradle bootRun
gradle test 
gradle test --tests org.gradle.SomeTestClass

7.1 Dockerize

Docker is the perfect quick containerized deployment tool.

If you intend to use Docker, you can define the Docker file as shown below:

FROM maven:3.6.3-jdk-8-slim AS build

COPY src /usr/src/app/src

COPY pom.xml /usr/src/app

RUN mvn -f /usr/src/app/pom.xml clean package

FROM openjdk:8-jdk-alpine

# Make port 8080 available to the world outside this container
EXPOSE 8080 

COPY --from=build /usr/src/app /usr/app/

# Run the jar file 
ENTRYPOINT ["java","","-jar","/usr/app/target/ussd-0.0.1-SNAPSHOT.jar"]

You can read about and run the following docker commands in the root folder of the project:

docker build -t myimage:1.0 .
docker image ls -a
docker pull myimage:1.0
docker push myrepo/myimage:2.0 
docker container run --name web -p 
docker container ls 

Docker has a free public hub where you can store and version your API docker images and find it here

React Native Customer Care Mobile App

1. Set Up the React Native project

Start a new React Native project and you can refer to this tutorial to install any required prerequisites tools and start a new project.

This section is not limited to a React App.

2. Install the Required Dependencies

  • Vector Icons
  • AfricasTalking Client SDK
  • Axios

Run the following command in the project root folder to install the required dependencies:

 npm install --save africastalking-client react-native-vector-icons axios

Ensure to follow all the setup options for the react-native-vector-icons package as shown here

3. Update the App.js directly

This being a demo project we will quickly modify the App.js file.

In a production application, you may need to set up your folder structure appropriately.

The App.js file will contain a called number text input, a call button and a hang-up button.

The App.js file imports the native elements of View, StyleSheet and other native components.

The installed modules i.e axios (for making HTTP requests), Africastalking (for Voice API Client Integration) and Feather (for the icons used) are also imported.

The constructor binds the button click events to the component.

The ComponentDidMount Lifecycle Method makes a request to AT capability token API to fetch a valid token and use it to initialize the AT Client. The AT capability Token API returns a response in the following format:

    "clientName": "somsom",
    "incoming": true,
    "lifeTimeSec": "86400",
    "outgoing": true,
    "token": "ATCAPtkn_206675b68efaff83d1ac2d027dd5bff18fd7cb64fgjhd5d0bdcsac44a883678afe7"

The callOrHangUpIcon function displays different icons depending on whether or not a call is ongoing.

4. Start, Run, Debug

To run your app follow step 2 and 3 of this tutorial

The app will run as follows:

Conclusion, Recommendation and Next Steps

React Native is a notable open-source mobile application framework relevant to the development of cross-platform applications.

Java Spring Boot is also a notable open-source Java-based framework used to create microservice setups of stand-alone and production-ready applications.

With the walk-through of this tutorial, you can now extend other functionalities offered by the AT Voice API to have a full-fledged call center. Additionally, in production setups database connections and security implementations are vital.

Find more code of this project on Github

You May Also Like