Fonoster provides capabilities for handling both inbound and outbound calls. Before making or receiving calls, you’ll need three key components:

  1. A SIP Trunk to connect to the telephony network
  2. A virtual phone number associated with your trunk
  3. An application to handle the call logic

Please see the Linking a Twilio number guide for a quick start.

Prerequisites

First, create an application that will handle your calls. You can do this using the SDK:

create-app.js
const SDK = require("@fonoster/sdk");

const client = new SDK.Client({ accessKeyId: "WO000000000000000000000000000000" });

const appConfig = {
  name: "My Calling App",
  type: "EXTERNAL",
  endpoint: "welcome.demo.fonoster.local", // Demo application
  speechToText: {
    productRef: "stt.deepgram",
    config: {
      languageCode: "en-US"
    }
  },
  textToSpeech: {
    productRef: "tts.deepgram",
    config: {
      voice: "aura-asteria-en"
    }
  }
}

client.loginWithApiKey("AP0eerv2g7qow3e950k7twu4rvydcunq3k", "fNc...")
  .then(async() => new SDK.Applications(client).createApplication(appConfig))
  .catch(console.error);

Or using the command-line tool:

fonoster applications:create

Inbound calls

You need a virtual phone number linked to your application to receive inbound calls. The easiest way to get started is with a Twillio number.

To link an application to a Twilio number, run the following command and follow the prompts:

fonoster sipnet:numbers:linkTwilioNumber

You are now ready to begin accepting inbound calls.

Outbound calls

You can make outbound calls using either the SDK or the command-line tool.

Using the SDK

call.js
const SDK = require("@fonoster/sdk");

const client = new SDK.Client({ accessKeyId: "WO000000000000000000000000000000" });

async function makeCall() {
  const calls = new SDK.Calls(client);
  const breakReasons = ["ANSWER", "NOANSWER", "BUSY", "FAILED", "CANCEL"];

  try {
    const { ref, statusStream } = await calls.createCall({
      from: "+18287854037",
      to: "+17853178070",
      // Replace with your application reference
      appRef: "4b01c9b1-8cb1-48fb-bd49-f3daf13463a9",
      timeout: 30
    });

    console.log(`Call created with reference: ${ref}`);

    // Monitor call status
    for await (const s of statusStream) {
      console.log(`Call status: ${s.status}`);
      if (breakReasons.includes(s.status)) {
        break;
      }
    }

    process.exit(0);
  } catch (err) {
    console.error("Error making call:", err);
  }
}

client.loginWithApiKey("AP0eerv2g7qow3e950k7twu4rvydcunq3k", "fNc...")
  .then(() => makeCall())
  .catch(console.error);

Using the command-line tool

First, get your application reference:

fonoster applications:list

Then make the call:

fonoster sipnet:calls:create \
  --app-ref 4b01c9b1-8cb1-48fb-bd49-f3daf13463a9 \ # Replace with your application reference
  --from +18287854037 \
  --to +17853178070

Call status monitoring

When using the SDK, you can monitor call status through the statusStream:

const { ref, statusStream } = await calls.createCall({
  from: "+18287854037",
  to: "+17853178070",
  appRef: "4b01c9b1-8cb1-48fb-bd49-f3daf13463a9"
});

// Monitor call status changes
for await (const status of statusStream) {
  switch(status) {
    case "RINGING":
      console.log("Call is ringing");
      break;
    case "IN_PROGRESS":
      console.log("Call is connected");
      break;
    case "COMPLETED":
      console.log("Call completed successfully");
      break;
    case "FAILED":
      console.log("Call failed");
      break;
  }
}