Building an IVR in Python to improve business scalability and customer experience

Two windows showing lines of code and rise in customer satisfaction

Notice: This post uses a legacy version of our API. Visit out developer portal to view current API documentation.

Scalability. This word gets thrown around a lot, but what does it mean? A quick Google search gives the definition of scalability as “the capacity to be changed in size or scale”.

Ok. Cool. So why is scalability important? Why do we want to achieve “the capacity to be changed in size or scale”? Because businesses, like everything else (our roads, our food supply, etc), need to be prepared to handle more.

As a business grows, it needs to be prepared to handle more customers, more support, more orders, more phone calls, emails, meetings; more of everything that impacts a business. Business growth is great, but a lack of resources is a bottleneck.

Hiring more employees is necessary for a growing business to keep its velocity. However, hiring new employees is hard. Resume’ reviews, interviews, and onboarding new employees takes time, and budgets don’t always exist. A business with good scalability needs to be able to achieve growth, as they may not always be able to rely on their ability to hire more employees.

Interactive Voice Response (IVR) systems are one way a business can improve scalability without hiring more employees. If you’re not sure what an IVR is, they’re a predefined system businesses often use to scale phone support and routing without having to talk to another human.

IVR use case

Here’s an example. I recently got a new Visa credit card and I had to activate it with a phone call. I called the phone number on my credit card and was asked by an automated response to use my phone’s keypad to input my 16-digit credit card number, expiration date, and security code. The system takes this information and activates my credit card. After this phone call, my card was activated without talking to another person.

Let’s say that Visa never set up this IVR for activating their credit cards and instead had a call center with hundreds of employees handling these credit card activation phone calls. What would’ve happened after I called the phone number on my credit card to activate it?

Without an automatic response, the first thing probably would be that I’d be placed on hold until an employee could get to my call. No worries, I’m a patient person. Once an employee is able to answer my call, I would need to tell this employee my credit card information, and this employee would need to manually confirm this information and then activate my card.

This setup of using a call center with hundreds of employees to handle credit card activation phone calls isn’t scalable. What would happen if Visa doubled the number of its customers, and therefore doubled the number of credit card activation phone calls? Visa would need to hire new employees in order to have twice as many call center employees—recruiting, interviewing, and training these new hires as well.

What would happen if the call center reached maximum capacity with all these new hires? Visa would need to buy land and build a new call center. How would this setup handle a sudden spike in phone call traffic? Would some employees need to be on-call to handle a spike in traffic? As you can see, the costs are insurmountable!

An IVR for handling credit card activation phone calls provides scalable answers to these questions. More customers for Visa, or experiencing spikes in traffic? Allocating more resources for the IVR is much easier than finding more employees to hire or participate in an on-call rotation.

According to this article from App Developer Magazine, the average cost of cloud computing has decreased by 58% per year over the last 3 years. With the cost of cloud computing decreasing, doubling the resources for an IVR is significantly less than trying to double the number of employees working in a call center. In addition, without having employees working at a call center, Visa wouldn’t even need to worry about building new call centers with hiring more employees.

This IVR setup also improves the customer’s experience. I don’t mind being on hold for a call, but I know there are some people who hate being on hold. An automated system keeps customers on hold much less and reduces the possibility of human error.

If I’m talking to another person and trying to tell them my credit card information, there’s a possibility of information loss with a bad connection or language barriers. Inputting my credit card information using my phone’s keypad is much less likely to result in information loss. Also, I don’t like knowing that other people know my credit card information, and I would rather avoid giving my credit card information to an employee when I could instead have an automated system handle it.

Code blocks

Using Bandwidth’s Voice API, you can create your own IVR. I’ve written a sample application using Python and Flask that can be found here. Code samples with descriptions are also included below. Our Voice and Messaging API Documentation also provides more information to allow you to create your own IVR to improve your business scalability!

Function that waits until the specified gather in the specified call is completed


def complete_gather(call_id, gather_id):
  """
  Waits for the gather to complete, then returns

  call_id: id of the call with the gather
  gather_id: id of the gather to wait on
  """
  data = VOICE_API.get_call_gather(call_id, gather_id)
  while data['state'] != 'completed':
      time.sleep(2)
      data = VOICE_API.get_call_gather(call_id, gather_id)

Example of how to get one digit from user input based on a spoken prompt

def get_user_input(call_id, prompt, mapping):
  """
  Plays a prompt on the current phone call, and speaks the
  number to product mapping to the user.

  Returns the mapping of the user's keypad input.
      user_keypad_input = keypad_input(call_id)
      return mapping[user_keypad_input]

  call_id: Bandwidth ID of the call to speak to
  prompt: User defined sentence to speak before the mapping
  mapping: data structure that maps a number (0-9) to a user output
      mapping = {
          0: "Pizza",
          1: "Taco"
      }
  """
  VOICE_API.play_audio_to_call(call_id, sentence=prompt)

  for keypad in mapping:
      VOICE_API.play_audio_to_call(call_id, sentence=keypad)
      VOICE_API.play_audio_to_call(call_id, sentence=mapping[keypad])

  gather_id = VOICE_API.create_call_gather(call_id, max_digits=1, inter_digit_timeout=30)
  complete_gather(call_id, gather_id)
  data = VOICE_API.get_call_gather(call_id, gather_id)
  return mapping[int(data['digits'])]

Example of how to get multiple digits from user input based on a spoken prompt


def get_credit_card(call_id):
  """
  Reads 16 keypad inputs to create a credit card payment

  call_id: The call_id to ask for input

  Returns a 16 digit string representing the credit card
  """
  VOICE_API.play_audio_to_call(call_id, sentence="Please input your 16 digit credit card")
  gather_id = VOICE_API.create_call_gather(call_id, max_digits=16)
  complete_gather(call_id, gather_id)
  data = VOICE_API.get_call_gather(call_id, gather_id)
  return data['digits']

Build easily with Bandwidth APIs

Integrate and build enterprise-ready conversations with Bandwidth’s APIs and our 24/7 support.

See the APIs