Build the future of communications.
Start building for free

Convert Fax-to-Email with Twilio Fax, Functions, TwiML Bins, and SparkPost


Today we’re going to use Twilio’s Fax API and SparkPost to receive an inbound fax and forward it as an outgoing email. We’ll use a phone number we purchase with Twilio and host our logic with the serverless Twilio Functions and TwiML Bins.

Sign Up For – Or Sign Into – A Twilio Account

You’ll be using a few Twilio products today to complete your quest: Twilio Programmable Fax for receiving an incoming fax and Twilio Functions and TwiML Bins to host your logic.

Either create a new Twilio account (sign up for a free Twilio trial), or sign into an existing Twilio account. Once you are logged in, open up a tab with the Functions Console. Then – leave it alone, we’ll come back to it later.

Purchase a Twilio Phone Number

Much like with phone calls and text messages you’ll need a phone number to accept incoming faxes. If you haven’t yet purchased a fax capable number, head over to the Buy a Phone Number section of the console.

Being sure to check the ‘Fax’ box in the capabilities section, purchase a phone number of your choice:

You will come back to this number later to direct incoming faxes. Next, let’s sort out the outgoing email bit by visiting SparkPost.

SparkPost Email API Key Generation Time!

We’re going to use SparkPost to handle the details of sending out emails containing a link to a PDF of our incoming faxes. To start things off with SparkPost, you’ll need to generate a new API key. If you haven’t yet, register a new account with SparkPost. Either way, login to your account with a mind to setting up some keys.

After that, go ahead and head to the SparkPost developer console and generate one there. Keep in mind that SparkPost API keys disappear once they’re generated, so go ahead and save that in a safe place for now.

Once you’re generated that key, open up your Twilio Console and head on over to the back to the  functions configuration section of the console. This is where you create environment variables to abstract some of the values you’ll need in your code from the logic itself – perfect for an API key like this.

Create a new environment variable called SPARKPOST_KEY and paste in that API key that you saved.

Now that we’ve gotten your SparkPost key configured, we’ll need to make sure that you’ll be able to use SparkPost’s Node.js SDK within Twilio Functions. On the functions configuration page you were you, add a new dependency and fill in SparkPost for the name. We’ve set the version to 2.1.2, which, at time of publication, is the latest.

Send out an Email with SparkPost and Twilio

We’ll need to set up a pair of Functions and a TwiML Bin to handle receiving the inbound fax and forwarding a link out to that fax. While forwarding the fax PDFs themselves is an option, we won’t be attaching the actual PDF to the email since it can grow pretty large.

Redirect to a Fresh Media URI

To start things off right, let’s head to the Manage Functions page and create a brand new function. Go ahead and select the ‘Blank’ template. The first function we are going to write will redirect you to a link to the PDF of your fax.

We have to redirect you to a fresh link because the publicly accessible links for media on Programmable Fax have a two hour time to live. (I personally don’t always check my email every two hours!)

Go ahead and name this function Redirect to Fax Media and set the path to /redirectToFaxMedia. You will need to make sure that “Check for valid Twilio signature” is unchecked — having it checked will prevent you from directly accessing that endpoint.

Once you have this set up, we’ll need to write some code that will take a faxSid as a URL parameter and redirect a user to the PDF for that fax.

**  /redirectToFaxMedia
**  Redirects the user to a fresh media_url for a given Fax SID
**  Under the hood, Programmable Fax generates media_urls with a ttl of 2 hours. If you
**  send someone a link to that media_url, it's likely that it will end up 404'ing. This
**  function will take a given faxSid and 302 redirect you to a fresh media_url.
**  This *must* be deployed with "Check for valid Twilio Signature" unchecked.
exports.handler = function(context, event, callback) {
  let res=new Twilio.Response();
  // We attempt to get the faxSid from our faxSid queryString parameter
    // If we find it, we 302 the user to the fresh media_url that was generated
    res.appendHeader('Location', data.mediaUrl);
    callback(null, res);
  // Otherwise return a 500 with the error as the message body
    callback(null, res);

In this piece of code, we use event.faxSid to get the faxSid from the querystring (e.g. We fetch that individual Fax, which contains a freshly generated mediaUrl.

Next, to redirect the user, we have to build a Twilio.Response object. We set the statusCode on the response object to be a 302 and set the Location header to be the mediaUrl that was returned on the resource.  We return this as part of the callback function upon success. This ends up redirecting the user to our freshly generated mediaUrl!

Email a Link to your Incoming Fax

Now that you have the redirect set up, we’ll need to write another function to actually send out the link to your incoming fax. Go back to the Manage Functions page and create a new function. You will want to select the ‘Blank’ template again. Go ahead and name this function Fax to Email and set the path to be /faxToEmail.

**  /faxToEmail
**  Takes an incoming Fax from Twilio and emails it out via SparkPost.
**  We're not directly attaching the file because of attachment size limits and the 
**  execution limit on functions (for the download). This function requires you to 
**  deploy a TwiML bin and the redirectToFaxMedia function too.
**  You will need to sign up for SparkPost and configure an environment variable called
**  SPARKPOST_KEY to use this. You can switch out SparkPost with your chosen mail engine.
const SparkPost=require('sparkpost');
const sp=new SparkPost(process.env.SPARKPOST_KEY);

// Fill this in with your email address
const yourEmailAddress='YOUR_EMAIL_ADDRESS';
const sendingEmail='SENDER_EMAIL_ADDRESS'

exports.handler = function(context, event, callback) {
  // redirectToFaxMedia is your function that redirects to a fresh Media URI. 
  const faxBaseUri='https://'+context.DOMAIN_NAME+'/redirectToFaxMedia?faxSid=';

  let text="You have a new Fax from "+event.From+" sent to your Twilio number! "+
        "Go ahead and check it out at "+faxBaseUri+event.FaxSid+"!";

  // Sends the email out using the SparkPost API.
    // We're disabling open_tracking
    options: {
      open_tracking: false,
      click_tracking: false
    }, content: {
      from: sendingEmail,
      subject: "You've got a new Fax Message from "+event.From+"!",
      text: text
    }, recipients: [
        address: yourEmailAddress
    callback(null, res);
    // Using callback() with a string will return a 500 w/ the string as the body. :)

This function is a bit longer than the previous one. You will need to replace the YOUR_EMAIL_ADDRESS and SENDER_EMAIL_ADDRESS placeholders with your email address and the email address that you wish to have the email sent from – or feel free to rewrite the code to pick up environment variables from your functions configuration instead. Keep in mind that the domain for that email will need to be a verified sending domain with SparkPost.  In your own inbox, don’t forget to whitelist the SENDER_EMAIL_ADDRESS that you specify above so your fax emails don’t get sent to spam!

Twilio Functions has a special parameter as part of its context object called DOMAIN_NAME — this resolves to your Functions URI. We use this to craft the base URI for the link that you will click on to access the PDF of your fax. We use event.FaxSid to get the FaxSid from the incoming Fax action request to complete out the URI. We then use the Transmissions API from SparkPost to send out an email containing the link you previously created. We’re setting the open_tracking and click_tracking options to false so that your URI does not get overwritten by SparkPost’s handy click tracking feature.

After you hit save, make sure to copy the full path for the Function. You will need this in a second to configure the TwimlBin you set up!

Configure A TwiML Bin to Accept Incoming Faxes

When Twilio receives an inbound fax to a number you have set up with us, we’ll need your application to tell us how to handle it. In this case, we’re going to use a TwiML Bin to send back the response. TwiML Bins are serverless ‘bins’ that can store the XML that makes up a response to Twilio.

Create a new TwiML Bin with the following piece of TwiML. Be sure to change the YOUR_REDIRECT_TO_FAX_MEDIA_URL_HERE  placeholder to be the URL that you copied when you created your /faxToEmail function. Go ahead and name this Fax to Email Bin.

<?xml version="1.0" encoding="UTF-8"?>

Seriously, that’s all you need to do! TwiML Bins are an easy, serverless way to host simple logic that doesn’t need the overhead of a full programming language. Next, let’s point the fax firehose (gardenhose?) at the Bin and complete the chain.

Connect a TwiML Bin to Your Phone Number

Now that you have your Functions and Bin written, you will need to head on over to the Manage Numbers section of the console and configure the number you’ve purchased. You will need to change the number to receive incoming Faxes.

Keep in mind that Twilio numbers can only either receive voice calls or receive faxes. For the “A Fax comes in” section, You will want to select the TwiML bin that you just created in the previous step. Once you hit the save button, you’re done and ready!

Bring Faxes Into the 20th Century with Email Forwarding

Now, all that’s left for you to do is try it!

Use your choice of Fax machine or other-Twilio-code pretending to be a fax machine to fax the phone number. You should quickly receive an email with the new link generated by your Twilio Function, mediated by the second Function and triggered by the TwiML Bin.

If that works, have confidence the setup will continue to run day and night forwarding those daily faxes you’re receiving to your inbox. You’ll also no longer have to worry about your cat attacking the faxes as they print.

Cat destroying an incoming fax

There you go – a cloud fax machine built with a few Twilio products and services and support from our friends at SparkPost (special thanks to Avi Goldman for the help!). Now it’s time for you to build one – we can’t wait to see what you fax!

Editor: Want to complete the circle? Our friends at Sparkpost posted a tutorial from the other direction, converting email to fax. Go check it out!

Patrick Kolencherry is a Contact Center Specialist at Twilio based in sunny Austin, Texas. According to Facebook’s ad targeting platform, his interests include “Water Treatment, Filtration, and Wave”  (we’re still confused by that one). You can get in touch with him on Twitter at @kolencherry.

Sign up and start building
Not ready yet? Talk to an expert.