Technical Success Manager
Olajide AwoyinkaThe SignalWire Fax API for developers
In an era dominated by instant messaging, email, and video calls, it's easy to assume that fax machines are a relic of the past. The truth is that modern faxing systems continue to play a significant role in many industries where secure and reliable document transmission is crucial. Recognizing this, SignalWire has revolutionized cloud-based faxing with its innovative platform, SignalWire Fax.
SignalWire’s programmable fax API combines the convenience of digital communication with the reliability and security of fax transmission, offering businesses a modern and efficient way to send and receive faxes in the digital age. By harnessing the power of the cloud, SignalWire Fax eliminates the need for traditional fax machines and phone lines, streamlining the entire faxing process.
You can get started with sending a fax by running a curl request as shown below:
To begin faxing in the cloud, you need to have a SignalWire Space, which will provide you with a ProjectID and the ability to create an API Token, which you will then use when calling the Fax API.
In this post, we’ll go through the steps for creating an application that allows you to send a fax with remote URL files or files stored on your Personal computer. You’ll need some basic knowledge of NodeJS, Express, and Ngrok in order to follow this example.
Getting Started with Programmable Fax
To start building our fax application we need to create a NodeJs environment, and we can do that by running the NodeJs command `npm init -y`. This command creates a basic NodeJs environment.
Here is what your package.json should look like after running the above command:
{ | |
"name": "fax-mini-project", | |
"version": "1.0.0", | |
"description": "", | |
"main": "index.js", | |
"scripts": { | |
"test": "echo \"Error: no test specified\" && exit 1", | |
"start": "node server.js" | |
}, | |
"keywords": [], | |
"author": "", | |
"license": "ISC", | |
"dependencies": { | |
"express": "4.18.2", | |
"cors": "2.8.5", | |
"formidable": "2.1.1", | |
"axios": "1.2.5", | |
"dotenv": "16.0.3" | |
}, | |
"devDependencies": { | |
"buffer": "^5.7.1" | |
} | |
} |
We’ve added some dependencies to allow us to make calls to the SignalWire Fax endpoint.
Run npm install to install all the dependencies.
Backend
We need to create a set of instructions that our web application will listen to. For example, whenever a user clicks on a button to send a fax, or whenever a user tries to select a file by clicking on the select file button.
Create a new file in your working directory and name it server.js. Then we can start adding blocks of code into the server.
Import Dependencies
First, we will import the dependencies needed in our application - the dependencies include Axios, express, dotenv, etc.
require("dotenv").config() | |
const express = require("express") | |
const cors = require("cors") | |
const formidable = require("formidable") | |
const axios = require("axios") | |
const fs = require("fs") |
Declare Global Variables
Next, we will create some variables that will be used to initialize our server, and some other variables to be used as authentication when we call the SignalWire Fax API.
const app = express() | |
const port = 8000 | |
const auth = { | |
username: process.env.PROJECT_ID, | |
password: process.env.API_TOKEN | |
} | |
// SignalWire Fax API | |
const url = `https://${process.env.SPACE_NAME}/api/laml/2010-04-01/Accounts/${process.env.PROJECT_ID}/Faxes` | |
app.use(express.static(__dirname)) |
You will notice the use of some environment variables like process.env.PROJECT_ID and process.env.SPACE_NAME. These are your credentials from your SignalWire space, so be sure to keep them safe.
Creating Environment Variables
Create your environment variable file where you will store your credentials obtained from your SignalWire space.
Create a file named .env and add the following line of code to the file:
PROJECT_ID=<YOUR-PROJECT-ID> API_TOKEN=<YOUR-API-TOKEN> SPACE_NAME=<YOUR-SPACE-NAME>.signalwire.com
Replace the items in the brackets with your actual credentials from your dashboard.
Create Endpoint to Send Fax
Back in the server.js file, we need to create an endpoint for whenever a user clicks on the submit button from our web application.
app.post("/save", async (req, res) => { | |
// Handling form submission | |
const form = new formidable.IncomingForm(); | |
// Parsing form submission | |
// fields parameters holds field from text, number Input | |
form.parse(req, function(err, fields, files) { | |
console.log(fields) | |
// If user has a file stored in a remote URL | |
// call the sendFax method while providing the appropriate field | |
// else store the file in the 'uploads' folder and generate a url | |
if (fields.selectionBtn === 'yes') { | |
const response = sendFax(res, fields.fileUrl, fields.fromPhone, fields.toPhone) | |
res.write("Fax sent successfully!") | |
res.end() | |
} else { | |
// Get current file path from local system storage | |
const oldPath = files.filetoupload.filepath | |
// set new path which is our "upload" folder in our directory | |
const newpath = __dirname + "/uploads/" + files.filetoupload.originalFilename | |
// move file from user directory to "uploads" directory | |
fs.rename(oldPath, newpath, async function(err) { | |
if (err) throw err; | |
// create an http url from the upload folder file path | |
let generatedUrl = "https://" + req.get('host') + "/uploads/" + files.filetoupload.originalFilename | |
// Call the send fax method that calls SW api | |
// it takes the generatedUrl | |
// fromPhone from the fields in the UI | |
// toPhone from the fields in the UI | |
const response = await sendFax(res, generatedUrl, fields.fromPhone, fields.toPhone) | |
// on Successful write the SID to the browser screen | |
res.write(`Success: ${response.sid}`) | |
res.end() | |
}) | |
} | |
}) | |
}) |
In the above code sample we are getting form data sent by the user on the frontend. The users have the option to send a media file from a remote URL or from their local computer. On a successful submission, it returns a response of the SID generated from the request.
You can also create a helper method used to call the SignalWire Fax API, which will make your code organized and clean.
/** | |
* Helper function to send fax using SW API | |
* | |
* @param {*} mediaUrl url path to the pdf in the "uploads" folder | |
* @param {*} from phone number you're sending the fax from | |
* @param {*} to destination phone number you're sending the fax to | |
* @returns | |
*/ | |
async function sendFax(res, mediaUrl, from, to) { | |
try { | |
console.log("Sending fax.......") | |
// Make API request to SW fax API providing the appropriate information. | |
const request = await axios.post(url, { | |
MediaUrl: mediaUrl, | |
To: to, | |
From: from | |
}, { auth }) | |
// return response data | |
return request.data | |
} catch (error) { | |
console.log("Sending fax error: ", error.response.data) | |
res.write(error.response.data.message) | |
res.end() | |
} | |
} |
Start Express application
Now we can configure the application to listen to a particular port by adding the following line at the end of the server.js file:
// App listening at port 8080 | |
app.listen(port, () => { | |
console.log(`App listening at port ${port}`) | |
}) |
Frontend
The frontend side of the application is where users can click on buttons and actually make use of the digital faxing service. To get started, we need to create a basic HTML file.
Creating HTML file
In the root folder, create a new file called index.html and add the following line of code:
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8" /> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
<title>Fax App</title> | |
<link rel="stylesheet" href=" | |
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous"> | |
</head> | |
<body> | |
<div class="container" style="width: 700px"> | |
<h1>Fax Presentation</h1> | |
<form action="save" method="post" enctype="multipart/form-data"> | |
<div class="form-group mb-3"> | |
<label>From:</label> | |
<input | |
type="text" | |
id="to-phone" | |
name="fromPhone" | |
class="form-control" | |
placeholder="from phone number" | |
/> | |
</div> | |
<div class="form-group mb-3"> | |
<label>To:</label> | |
<input | |
type="text" | |
id="to-phone" | |
name="toPhone" | |
class="form-control" | |
placeholder="To phone number" | |
/> | |
</div> | |
<div class="form-group mb-3"> | |
<label>Do you have a remote URL</label> | |
<div class="form-check"> | |
<input | |
class="form-check-input" | |
type="radio" | |
value="yes" | |
name="selectionBtn" | |
id="selectionBtn1" | |
checked | |
/> | |
<label class="form-check-label" for="selectionBtn1"> | |
Yes | |
</label> | |
</div> | |
<div class="form-check"> | |
<input | |
class="form-check-input" | |
type="radio" | |
value="no" | |
name="selectionBtn" | |
id="selectionBtn2" | |
/> | |
<label class="form-check-label" for="selectionBtn2"> No </label> | |
</div> | |
</div> | |
<div class="form-group mb-3" id="fileURL"> | |
<label for="remoteUrl">File remote URL</label> | |
<input type="text" id="fileUrl" class="form-control" name="fileUrl"/> | |
</div> | |
<div class="form-group mb-3" id="fileUpload"> | |
<label>Upload file</label> | |
<input | |
type="file" | |
id="file-input" | |
name="filetoupload" | |
class="form-control" | |
accept="application/pdf" | |
placeholder="To phone number" | |
/> | |
</div> | |
<div class="row mt-3"> | |
<button class="btn btn-primary" type="submit">Submit</button> | |
</div> | |
</form> | |
</div> | |
<script type="module" src="index.js"></script> | |
<script src=" | |
https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ENjdO4Dr2bkBIFxQpeoTz1HIcje39Wm4jDKdf19U8gI4ddQ3GYNS7NTKfAdVQSZe" crossorigin="anonymous" | |
></script> | |
</body> | |
</html> |
Create JS file
We need to create a javascript file for the use of the form in our web application. To do this, make a new file in the root directory of your project and call it index.js.
Add the following line of code to your index.js file:
const fileUrlDom = document.getElementById("fileURL") | |
const fileUploadDom = document.getElementById("fileUpload") | |
fileUploadDom.style.display = "none" | |
document.body.addEventListener('change', function(e){ | |
let target = e.target | |
switch(target.id){ | |
case 'selectionBtn1': | |
fileUploadDom.style.display = "none" | |
fileUrlDom.style.display = "block" | |
break | |
case 'selectionBtn2': | |
fileUploadDom.style.display = "block" | |
fileUrlDom.style.display = "none" | |
} | |
}) |
Run the Fax Application
Now that we have the frontend and backend set up, open a terminal and navigate to your working directory. Run the following command to start up the application:
node server.js
The above command will start off both the frontend and backend of the application. If you navigate to http://localhost:8000 you should see the following result:
If you would like a live example, you can find that here.
Start ngrok
Finally, run ngrok to get a remote URL that will tunnel the URL request to our running web application.
You must have ngrok installed. To install ngrok follow this tutorial. Open another terminal, and run the below command to start ngrok:
ngrok http 8000
The above command provides you with a public URL that can be accessed on your web browser. With that, you should be able to access the simple fax application.
We want to see what you build with SignalWire! If you have any questions while getting started with our Fax API, stop by our Community Slack or our Forum to connect with our team.