You can build extremely powerful and flexible contact center solutions with the Vonage Voice API. But what happens if there’s no one there to answer the phone on the other end? Well, I suppose you could just simply let the phone ring or play a message back asking them to call again later. Probably what most people would do, including myself, is to take the customer’s message in the form of a voicemail. With the Vonage Voice API and our .NET SDK, this is a snap to do in ASP.NET Core!
There are multiple ways to record phone calls with the Vonage Voice API. In this tutorial, we will be using an Answer webhook, which will return a Nexmo Call Control Object(NCCO) containing an action telling Vonage to record the call and then post back the recording’s URL to our server when the call concludes. A webhook is simply a publicly available HTTP endpoint that Vonage will reach out to for instructions when it gets a call.
If you would like to skip this tutorial and just look at the code, you can find all the code for this tutorial in GitHub.
To complete this tutorial, you will need a Vonage API account. If you don’t have one already, you can sign up today and start building with free credit. Once you have an account, you can find your API Key and API Secret at the top of the Vonage API Dashboard.
With npm installed we can go ahead and install and configure the Nexmo CLI using:
npm install nexmo-cli -g
nexmo setup API_KEY API_SECRET
Running this will get the Nexmo CLI setup and ready to run.
I’m going to be throwing everything on localhost:5000
. Running ngrok will allow us to publicly access localhost:5000
.
ngrok http --host-header=localhost:5000 5000
Take a note of the URL that ngrok is running on. In my case, it’s running on http://7ca005ad1287.ngrok.io
. This URL is going to be the base URL for my webhooks going forward.
A Vonage Application is a construct that enables us to link route our numbers and webhooks easily. You can create an application in the Vonage Dashboard, or you can just make it now with the CLI.
nexmo app:create "AspNetTestApp" http://7ca005ad1287.ngrok.io/webhooks/answer http://7ca005ad1287.ngrok.io/webhooks/events
These commands are going to create a Vonage Application. It’s going to then link all incoming calls to that application to the answer URL: http://7ca005ad1287.ngrok.io/webhooks/answer
and route all call events that happen on that application to http://7ca005ad1287.ngrok.io/webhooks/events
. This command is going to print out two things:
private.key
When you create your account, you are assigned a Vonage number. You can see this in the numbers section of the dashboard. Or you could alternatively just run nexmo number:list
in your console to list your numbers. Take your Vonage Number and your Application ID and run the following:
nexmo link:app VONAGE_NUMBER APPLICATION_ID
With this done, your calls are going to route nicely to your URL.
To create your project:
The only dependency this is going to have is the Nexmo.Csharp.Client
NuGet package. Go ahead and grab that using your preferred method. Mine is to navigate to the VonageVoicemail.csproj
’s directory and run:
dotnet add package Nexmo.Csharp.Client
If you’re feeling lazy, you could piggyback off the WeatherForecastController
that’s pre-generated. But for our purposes we’ll create a new controller by right-clicking on the Controllers
folder -> Add -> Controller -> Select API Controller - Empty
-> click Add -> Name this VoiceController
.
These steps will create an empty API controller.
We’ll need access to the app’s configuration for this. In the VoiceController, declare an IConfiguration object, and then dependency injects an IConfiguration into the controller’s constructor.
private readonly IConfiguration _config;
public VoiceController(IConfiguration config)
{
_config = config;
}
Now that we have our API controller built, let’s add an answer route. We’ll add an Answer
method at the end of this route, which will create an NCCO with two actions:
[HttpGet]
[Route("webhooks/answer")]
public async Task<string> Answer()
{
var host = Request.Host.ToString();
//remove the next line if using ngrok without --host-header option
host = Request.Headers["X-Original-Host"];
var sitebase = $"{Request.Scheme}://{host}";
var talkAction = new TalkAction
{
Text = "Hello, you have reached Steve's number," +
" he cannot come to the phone right now. " +
"Please leave a message after the tone.",
VoiceName = "Joey"
};
var recordAction = new RecordAction
{
EndOnSilence = "3",
BeepStart = "true",
EventUrl = new[] { $"{sitebase}/webhooks/recording" },
EventMethod = "POST"
};
var ncco = new Ncco(talkAction, recordAction);
return ncco.ToString();
}
Important:
host = Request.Headers["X-Original-Host"];
allows you to get the appropriate callback URL when using ngrok with the-host-header
option. Remove this if you’re not using it.
After recording the call, Vonage will post a response back to you on the EventUrl
you provided. From that POST request, we will extract the Recording URL. Then we’ll create a voice client from our credentials, which we’ll store in the configuration. With the voice client, we will get the recording, and then save it to an mp3 file on our disk.
[HttpPost]
[Route("webhooks/recording")]
public IActionResult Recording()
{
Record record;
var appId = _config["APP_ID"];
var privateKeyPath = _config["PRIVATE_KEY_PATH"];
var credentials = Credentials.FromAppIdAndPrivateKeyPath(appId, privateKeyPath);
var voiceClient = new VoiceClient(credentials);
using (StreamReader reader = new StreamReader(Request.Body, Encoding.UTF8))
{
record = JsonConvert.DeserializeObject<Record>(reader.ReadToEndAsync().Result);
var recording = voiceClient.GetRecording(record.RecordingUrl);
System.IO.File.WriteAllBytes("your_recording.mp3", recording.ResultStream);
}
Console.WriteLine($"Record event received on webhook - URL: {record?.RecordingUrl}");
return StatusCode(204);
}
That’s all the C# code you’re going to need for this. Next, let’s go ahead and configure the app!
There are two types of configuration we’ll need to perform.
http://localhost:5000
Open appsettings.json
and add the keys APP_ID
and PRIVATE_KEY_PATH
to it, utilizing the application Id and the Private key that we generated with the CLI earlier. Those keys in JSON will look like:
"APP_ID": "7h15-w111-83-y0u2-4pp-1d",
"PRIVATE_KEY_PATH": "C:\\path\\to\\your\\private.key"
Now we need to update the launch settings file to have IIS Express or Kestrel listen on http://localhost:5000
. Open properties/launchSettings.json
; if you are using IIS Express, change the application URL in the iisSettings object to http://localhost:5000
and set the sslPort to 0 to disable SSL. If you are using Kestrel, remove the https://localhost:5001
endpoint leaving only the http://localhost:5000
endpoint.
That’s all we need to do before running the app. You can run the app from Visual Studio by pressing F5, or from the command line by running dotnet run
. If you call your Vonage API number, it will play the outgoing message, record the caller after the beep, and then when the call concludes, save a recording of the call to your disk.