# Make a call and basic IVR menu with Node.js

You can quickly see how the Voice API works by calling yourself using the API and playing a basic IVR menu.

## What you need to know before you start

Before you can get started, you need the following already set up:

* Set all Voice API [configuration settings](/docs/voice/getting-started).
* [NPM](https://www.npmjs.com/) and a familiarity with how to install packages.
* [Node.js](https://nodejs.org/en/) and a familiarity with how to create a new app.
* [Ngrok](https://ngrok.com/) to create a public URL to your localhosted node backend


## Set up your Node.js application

Create a new node app with npm.

```shell
npm init
```

Accept the defaults for the application.

### Install your dependencies

Add the fetch package with npm to generate the necessary dependencies.

```shell
npm install 'body-parser'
npm install 'express'
npm install 'axios'
npm install 'ngrok'
```

## Create the files you will need

Create a new file named **index.js** in the project and paste the provided "index.js" code into the file.

index.js
```javascript index.js
const express = require('express');
const bodyParser = require("body-parser");
const ngrok = require('ngrok');
const axios = require('axios')

const PORT = 8081;

const app = express();
app.use(bodyParser.json());

const APPLICATION_KEY = ''
const APPLICATION_SECRET = ''
const CLI = ''
const TO_NUMBER = ''
const eq = '\"'

app.post('/', async (req, res) => {
  let eventName = req.body.event;
  //console.log(`:: INCOMING HTTP BODY :: ", req.body)
  switch (eventName){
    case 'pie':
      var value = req.body.menuResult.value;
      console.log(`:: INCOMING EVENT ::`, req.body.event)
      //console.log(`:: INCOMING EVENT BODY ::`, req.body)
      console.log(`:: IVR MENU CHOICE :: Destination: `, TO_NUMBER, `selected value: `, value);
    case 'dice':
      console.log(`:: INCOMING EVENT ::`, req.body.event)
      //console.log(`:: INCOMING EVENT BODY ::`, req.body)
      res.sendStatus(200);
      break;
    default:
      //console.log(`:: INCOMING HTTP BODY::`, req.body)
      console.log(`:: ERROR ::  Sorry, there was an error with your request. Please inspect HTTP body above`);
      res.sendStatus(404);
  }
});

function calloutRunMenu(url) {
    axios({
      method: 'post',
      url: 'https://calling.api.sinch.com/calling/v1/callouts',
      data: {
        "method": "CustomCallout",
        "customCallout": {
          "ice": "{\"action\": {\"name\": \"ConnectPstn\",\"number\": "+eq+TO_NUMBER+eq+",\"cli\": "+eq+CLI+eq+"}}",
          "ace": "{\"action\": {\"name\": \"RunMenu\",\"locale\": \"en-US\",\"menus\": [{\"id\": \"main\",\"mainPrompt\": \"#tts[ Welcome to the main menu. Press 1 to confirm order or 2 to cancel]\",\"timeoutMills\": 5000,\"options\": [ {\"dtmf\": \"1\",\"action\": \"return(confirm)\"}, {\"dtmf\": \"2\",\"action\": \"return(cancel)\"}]}]}}",
          "pie" : url,
          "dice" : url
        }},
      auth: {
          username: APPLICATION_KEY,
          password: APPLICATION_SECRET
        },   
        headers: {
          'content-type': 'application/json'
      }
    }).then((response) => {
        console.log(`:: INFO :: Custom Callout Data: ${response.config.data}`); 
        }, (error) => {
          console.log(error);
        });
};

app.listen(PORT, async () => {
  const url = await ngrok.connect(PORT);
  console.log(`:: INFO :: Node.js local server is publicly-accessible at ${url}/`);
  console.log(`:: INFO :: Listening at http://localhost:` + PORT);
  console.log(`:: INFO :: CustomCallout initiated with outgoing IVR`);
  calloutRunMenu(url);
});
```

## Fill in your parameters

Assign your values to the following parameters:

| Parameter | Your value |
|  --- | --- |
| `APPLICATION_KEY` | The key found on your Sinch [dashboard](https://dashboard.sinch.com/voice/apps). |
| `APPLICATION_SECRET` | The secret found on your Sinch [dashboard](https://dashboard.sinch.com/voice/apps). |
| `CLI` | Any purchased number you have with us on your account. Find the number on your Sinch [dashboard](https://dashboard.sinch.com/voice/apps) by clicking on your app, navigating to the Voice and Video tab, and looking in the Inbound Numbers section. |
| `TO_NUMBER` | The phone number that you want to call. |


Save the file.

## CustomCallout RunMenu and parsing the choice made

Now you can execute the code and make your text-to-speech call. Run the following command:

```shell
node index.js
```

The node listener will start, you will see your custom data that is sent.

```logs
INFO :: Node.js local server is publicly-accessible at https://ffff-ff-fff-fff-ff.ngrok.io
INFO :: Listening at http://localhost:8081
INFO :: CustomCallout initiated with outgoing IVR
INFO :: Custom Callout Data:
{ "Method":"CustomCallout","customCallout":{"ice":"{\"action\": {\"destination\": {\"type\": \"number\",\"endpoint\": \"+00000000000\"  },\"cli\": \"+00000000000\",\"name\": \"ConnectPstn\"}}","ace":"{\"action\": {\"name\": \"RunMenu\",\"locale\": \"en-US\",\"menus\": [{\"id\": \"main\",\"mainPrompt\": \"#tts[ Welcome to the main menu. Press 1 to confirm order or 2 to cancel]\",\"timeoutMills\": 5000,\"options\": [ {\"dtmf\": \"1\",\"action\": \"return(confirm)\"}, {\"dtmf\": \"2\",\"action\": \"return(cancel)\"}]}]}},"pie":"https://ffff-ff-fff-fff-ff.ngrok.io","dice":"https://ffff-ff-fff-fff-ff.ngrok.io"}}
```

You will recieve a callout to your selected number. Once a choice is made the PIE event will be returned to the callback server stated in the `pie` section of the customCallout.
There are two possible choices as per the configured RunMenu (IVR) which are `confirm` or `cancel`.  You will see in this message what choice was made, the `Destination` will show the `TO_NUMBER` you dialed.

```logs
INCOMING EVENT :: pie
IVR MENU CHOICE :: Destination:  "+00000000000" selected value:  confirm"
```

## Bonus: Inspect the incoming HTTP Call Event bodies

If you uncomment the `//console.log(`:: INCOMING HTTP BODY :: ", req.body)` lines to see the incoming call requests (example `pie` event below)
This will give you a better visibility whilst developing and debugging your incoming call events.

```logs
 :: INCOMING HTTP BODY ::  {
   event: 'pie',
   callid: '00000000-dddd-2222-eeee-444444444444',
   timestamp: '2022-02-14T10:53:16Z',
   menuResult: {
     addToContext: [],
     type: 'return',
     value: 'confirm',
     menuId: 'main',
     inputMethod: 'dtmf'
   },
   version: 1,
   applicationKey: '11111111-aaaa-2222-bbbb-333333333333'
 }
```

## Next steps

The code you used in the **index.js** file sends a POST request to the Sinch API **/callouts** endpoint to make the call. Click [here](/docs/voice/api-reference/voice/callouts) to read more about the /callouts endpoint.

- [API specification](/docs/voice/api-reference/voice)