Store call recordings on a dedicated server
Import your recordings and voicemail in your infrastructure and add an extra layer of security.

The objective of this tutorial is showing how we can download recordings in order to store them in a specific database.

Call recordings and call voicemails can be deleted using the Aircall Public API. We will implement deletion of those two types in this tutorial.

Getting started

Before starting to code, you will need to have:

  • An Aircall account - sign up here if you don't have one yet.
  • A web server running your application with a valid webhook endpoint. Check the Create a Webhook integration tutorial to learn more about it.
  • And enough space on your web server to store audio recordings.

Steps

  1. Listen for call.ended events
  2. Download the recording file
  3. Delete audio recording from Aircall database
  4. Bonus: Fetch old calls' recording

1. Listen for call.ended events

Every time a call is over, Aircall will send two Webhook events:

  • call.hungup, sent right after the caller or callee hung up.
  • call.ended, sent around 30 seconds after the call is done, with extra data like the recording file.

We will use the call.ended event in this tutorial.

First, create a Webhook in your Aircall Dashboard, sending call.ended events to following URL:

https://your.server.com/aircall/call_ended

Aircall Dashboard - New webhook

Now that the Webhook is created, we can setup the endpoint on our web server:

javascript
/** * server.js * Using express to run a NodeJS server */ const express = require('express'), bodyParser = require('body-parser'); const app = express(); app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.json()); // [POST] /aircall/call_ended // URL used by Aircall to send Webhook events app.post('/aircall/call_ended', (req, res) => { if (req.body.event === 'call.created') { // TODO: Do something with this event } else { console.log('Event non-handled:', req.body.event); } res.sendStatus(200); }); const PORT = 5000; app.listen(PORT, () => { console.info('[server] server started'); console.info('[server] visit http://localhost:' + PORT); });

2. Download the recording file

We now have a web server up and running, with a [POST] /aircall/call_ended endpoint listening for Webhook events sent by Aircall.

A Call object is attached to each Webhook event sent by Aircall:

json
{ "event": "call.ended", "resource": "call", "timestamp": 1585002050, "token": "45XXYYZZa08", "data": { "id": 812, ... "asset": "https://assets.aircall.io/recording/812", "recording": "https://aircall.s3.us-west-2.amazonaws.com/recordings/call-47cXYZ06-liverecord.mp3?token=54BDSJ5654ASF", "voicemail": null, ... } }

The payload body contains lots of information, let's focus on three of them:

  • data.asset: a secured webpage containing the voicemail or live recording for this Call. Users will need to authenticate in order to listen to the recording.
  • data.recording: the direct URL of the live recording (mp3 file) for this Call. Only present if call has been answered.
  • data.voicemail: the direct URL of a voicemail (mp3 file) for this Call. Only present if a voicemail was left.

Note that recording and voicemail URLs are valid for only 10 minutes. This is a security measure to ensure there are no direct link to a recording or voicemail file available long-term.

Once you parse this JSON object and focus on data.recording or data.voicemail, you can use your favorite library to directly download your recording and store it in your warehouse:

javascript
/** * server.js */ // 1. Require fs, http and url to download the audio file const express = require('express'), bodyParser = require('body-parser'), fs = require('fs'), http = require('https'), url = require('url'); // 2. Update that path according to your web server structure: const DOWNLOAD_DIRECTORY = '/your/path/to/recordings/'; ... // [POST] /aircall/call_ended // URL used by Aircall to send Webhook events app.post('/aircall/call_ended', (req, res) => { if (req.body.event === 'call.created') { downloadRecording(req.body.data); } else { console.log('Event non-handled:', req.body.event); } res.sendStatus(200); }); // Downloads voicemail and live recordings on the web server const downloadRecording = (callPayload) => { if (!callPayload) { console.warn('callPayload is not defined'); return; } // 3. Get live recording or the voicemail URLs: let callAudioURL = callPayload.recording || callPayload.voicemail; if (!callAudioURL) { console.warn('call has no recording or voicemail attached'); return; } // 4. Define HTTP options const httpOptions = { host: url.parse(callAudioURL).host, port: 443, path: url.parse(callAudioURL).pathname }; // 5. Specify the full path of where the audio file will be downloaded const recordingFilePath = DOWNLOAD_DIRECTORY + 'call_recording_' + callPayload.id + '.mp3'; // 6. Declare a stream that we'll write into let file = fs.createWriteStream(recordingFilePath); // 7. Send the HTTP Get request and write in the file stream: http.get(httpOptions, (res) => { res.on('data', (data) => { file.write(data); }).on('end', () => { console.log('Call successfully downloaded!') file.end(); }); }); } ...

3. Delete audio recording from Aircall database

If you're looking for an extra layer of security, recordings can be deleted from Aircall once the audio file has been downloaded.

You would only need the call ID and one of the following DELETE HTTP requests:

[DELETE] https://api.aircall.io/v1/calls/:call_id/recording
[DELETE] https://api.aircall.io/v1/calls/:call_id/voicemail

The call ID is present in the Webhook event payload, under the id field.

You'll need to know how to use Basic Authentication for this step, please read the Basic Authentication tutorial first! In the following example, we will assume that you already have your API ID and API Token credentials ready.

javascript
/** * server.js */ const express = require('express'), bodyParser = require('body-parser'), fs = require('fs'), http = require('https'), url = require('url'); const apiId = "YOUR_API_ID"; const apiToken = "YOUR_API_TOKEN"; ... // [POST] /aircall/call_ended // URL used by Aircall to send Webhook events app.post('/aircall/call_ended', (req, res) => { if (req.body.event === 'call.created') { downloadRecording(req.body.data); deleteRecording(req.body.data); } else { console.log('Event non-handled:', req.body.event); } res.sendStatus(200); }); // Downloads voicemail and live recordings on the web server const downloadRecording = (callPayload) => { // Implemented in Step 2 of this tutorial ... } // Delete voicemail and live recordings on the web server const deleteRecording = (callPayload) => { if (!callPayload) { console.warn('callPayload is not defined'); return; } if (!callPayload.recording && !callPayload.voicemail) { console.warn('call has no recording or voicemail attached to delete'); return; } // Define the audio type, either voicemail or recording const type = !!callPayload.voicemail ? 'voicemail' : 'recording'; // Build the URL path const urlPath = '/v1/calls/' + callPayload.id + '/' + type; // Encore API credentials let encodedCredentials = Buffer.from(apiId + ':' + apiToken).toString('base64'); // Define the HTTP options let options = { host: 'api.aircall.io', port: 443, path: urlPath, method: 'DELETE', headers: { 'Authorization': 'Basic ' + encodedCredentials } }; // Define the DELETE request: const req = http.request( options, res => { res.on('end', () => { console.log('Audio file deleted!') }); } ); req.end(); } ...

After the files being deleted from Aircall' servers with the Public API, they won't be available anymore from the Aircall Dashboard and Phone apps - please proceed with caution!

After downloading audio files on your server, we now delete the associated recording and voicemail files from Aircall!

Bonus: Fetch old calls' recording

We've implemented Webhook events in this tutorial to get recordings of new calls made by your team, but you could definitely apply the same store & delete logic with old calls!

To retrieve old calls made on your Aircall account, you could use the Batch syncing method described in our Logging calls in your database tutorial with the [GET] /v1/calls endpoint, described here.

📑
Logging calls in your database
Best practices to know before storing calls metadata

We wrote other tutorials to help you out
building awesome integrations

Discover them now